library(beeswarm)
library(naniar)
library(zoo)

Attaching package: ‘zoo’

The following objects are masked from ‘package:base’:

    as.Date, as.Date.numeric
# install.packages("zoo")
library(janitor)

Attaching package: ‘janitor’

The following objects are masked from ‘package:stats’:

    chisq.test, fisher.test
library(dplyr)

Attaching package: ‘dplyr’

The following objects are masked from ‘package:stats’:

    filter, lag

The following objects are masked from ‘package:base’:

    intersect, setdiff, setequal, union
# install.packages("GGally")
# library(sets)
library(tidyverse)
Registered S3 methods overwritten by 'dbplyr':
  method         from
  print.tbl_lazy     
  print.tbl_sql      
── Attaching packages ──────────────────────────────────────────────────────────────────────── tidyverse 1.3.0 ──
✓ ggplot2 3.3.3     ✓ purrr   0.3.4
✓ tibble  3.0.6     ✓ stringr 1.4.0
✓ tidyr   1.1.2     ✓ forcats 0.5.1
✓ readr   1.4.0     
── Conflicts ─────────────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
x dplyr::filter() masks stats::filter()
x dplyr::lag()    masks stats::lag()
library(ggplot2)
library(GGally) # for ggpairs
Registered S3 method overwritten by 'GGally':
  method from   
  +.gg   ggplot2
library(lubridate)

Attaching package: ‘lubridate’

The following objects are masked from ‘package:base’:

    date, intersect, setdiff, union
# install.packages("maps")
# library(maps)
load_file <- function(file_path){
  read_csv(file_path)
}

tx_data <- load_file("./../data/COVID-19_cases_TX.csv")

── Column specification ─────────────────────────────────────────────────────────────────────────────────────────
cols(
  county_fips_code = col_character(),
  county_name = col_character(),
  state = col_character(),
  state_fips_code = col_double(),
  date = col_date(format = ""),
  confirmed_cases = col_double(),
  deaths = col_double()
)
global_mobility_report <- load_file("./../data/Global_Mobility_Report.csv")

── Column specification ─────────────────────────────────────────────────────────────────────────────────────────
cols(
  country_region_code = col_character(),
  country_region = col_character(),
  sub_region_1 = col_character(),
  sub_region_2 = col_logical(),
  metro_area = col_logical(),
  iso_3166_2_code = col_character(),
  census_fips_code = col_logical(),
  date = col_date(format = ""),
  retail_and_recreation_percent_change_from_baseline = col_double(),
  grocery_and_pharmacy_percent_change_from_baseline = col_double(),
  parks_percent_change_from_baseline = col_double(),
  transit_stations_percent_change_from_baseline = col_double(),
  workplaces_percent_change_from_baseline = col_double(),
  residential_percent_change_from_baseline = col_double()
)

4199216 parsing failures.
 row        col           expected                  actual                                   file
3036 metro_area 1/0/T/F/TRUE/FALSE Kabul Metropolitan Area './../data/Global_Mobility_Report.csv'
3037 metro_area 1/0/T/F/TRUE/FALSE Kabul Metropolitan Area './../data/Global_Mobility_Report.csv'
3038 metro_area 1/0/T/F/TRUE/FALSE Kabul Metropolitan Area './../data/Global_Mobility_Report.csv'
3039 metro_area 1/0/T/F/TRUE/FALSE Kabul Metropolitan Area './../data/Global_Mobility_Report.csv'
3040 metro_area 1/0/T/F/TRUE/FALSE Kabul Metropolitan Area './../data/Global_Mobility_Report.csv'
.... .......... .................. ....................... ......................................
See problems(...) for more details.
cases_plus_census <- load_file("./../data/COVID-19_cases_plus_census.csv")

── Column specification ─────────────────────────────────────────────────────────────────────────────────────────
cols(
  .default = col_double(),
  county_fips_code = col_character(),
  county_name = col_character(),
  state = col_character(),
  state_fips_code = col_character(),
  date = col_date(format = ""),
  geo_id = col_character(),
  pop_5_years_over = col_logical(),
  speak_only_english_at_home = col_logical(),
  speak_spanish_at_home = col_logical(),
  speak_spanish_at_home_low_english = col_logical(),
  pop_15_and_over = col_logical(),
  pop_never_married = col_logical(),
  pop_now_married = col_logical(),
  pop_separated = col_logical(),
  pop_widowed = col_logical(),
  pop_divorced = col_logical()
)
ℹ Use `spec()` for the full column specifications.
cols_keep <- c("county_fips_code", "confirmed_cases", "deaths", "median_income", "male_pop", "female_pop", "total_pop", "median_age", "worked_at_home", "male_65_to_66", "male_67_to_69", 
               "male_70_to_74", "male_75_to_79", "male_80_to_84",
               "male_85_and_over", "female_65_to_66", "female_67_to_69", 
               "female_70_to_74", "female_75_to_79", "female_80_to_84",
               "female_85_and_over")
subset_census <- cases_plus_census[cols_keep]

subset_census$male_elderly_pop <- subset_census %>% select(c("male_65_to_66",
                                                             "male_67_to_69", 
                                                             "male_70_to_74",
                                                             "male_75_to_79",
                                                             "male_80_to_84",
                                                             "male_85_and_over")
                                                           ) %>% rowSums()

subset_census$female_elderly_pop <- subset_census %>% select(c("female_65_to_66",
                                                             "female_67_to_69", 
                                                             "female_70_to_74",
                                                             "female_75_to_79",
                                                             "female_80_to_84",
                                                             "female_85_and_over")
                                                           ) %>% rowSums()

cols_keep <- c("county_fips_code", "confirmed_cases", "deaths", "median_income",
               "male_pop", "female_pop", "total_pop", "median_age",
               "worked_at_home", "male_elderly_pop", "female_elderly_pop")
subset_census <- subset_census[cols_keep]
subset_census

# cols_keep <- c("date", "retail_and_recreation_percent_change_from_baseline", "grocery_and_pharmacy_percent_change_from_baseline", "parks_percent_change_from_baseline", "transit_stations_percent_change_from_baseline", "workplaces_percent_change_from_baseline", "residential_percent_change_from_baseline")
# subset_mobility <- global_mobility_report[cols_keep]
# glo
# subset_mobility$date <- as.Date(subset_mobility$date, format="%Y-%m-%d")
# global_mobility_report
vis_miss(global_mobility_report, sort_miss = T, warn_large_data= F)

vis_miss(tx_data, sort_miss = T, warn_large_data= F)

vis_miss(subset_census, sort_miss = T, warn_large_data = F)

library(RColorBrewer)
plot_vs_county <- function(df, col_val, percentile=FALSE,
                           fips_title="county_fips_code", banks=6, 
                           legend_title="", graphic_title=""){
  # Subset for speed 
  df <- df[c(fips_title, col_val)]
  
  # Get county data
  gcounty <- ggplot2::map_data("county")
  # USA map data
  gusa <- map_data("state")
  
  if (banks > 9){
    mycolors <- colorRampPalette(brewer.pal(9, "Reds"))(banks)
  }
  
  # Format with subregions
  fipstab <-
      transmute(maps::county.fips, fips, county = sub(":.*", "", polyname)) %>%
      unique() %>%
      separate(county, c("region", "subregion"), sep = ",")
  
  # Combine in desired order (NA for missing)
  gcounty <- left_join(gcounty, fipstab, c("region", "subregion"))


  dis <- df
  dis$rprop <- rank(df[col_val])
  dis$pcls <- cut(100 * percent_rank(df[col_val]), seq(0, 100, len = banks),
                        include.lowest = TRUE)

  # Missing data
  anti_join(gcounty, dis, by = c("fips" = fips_title)) %>%
    select(region, subregion) %>%
    unique()
  gcounty_pop <- left_join(gcounty, dis, by = c("fips" = fips_title))
  fill_vals <- gcounty_pop[col_val]

  # Plot
  if (legend_title == ""){
    legend_title <- col_val
  }

  if (percentile == FALSE){
    # names(gcounty_pop)[names(gcounty_pop) == col_val] <- "col_of_interest"
    plt <- ggplot(gcounty_pop) +
      geom_polygon(aes(long, lat, group = group, fill = get(col_val)),
                   color = "grey", size = 0.1, name="Percent Infected") +
      geom_polygon(aes(long, lat, group = group),
                   fill = NA, data = gusa, color = "lightgrey") +
      coord_map("bonne", parameters = 41.6) + ggthemes::theme_map()+
      scale_fill_gradient2()
       # scale_fill_gradient(low = "white", high = "red", na.value = "grey")
      # scale_fill_gradientn(colours = terrain.colors(10))
  }

  if (percentile == TRUE){
    plt <- ggplot(gcounty_pop) +
      geom_polygon(aes(long, lat, group = group, fill = pcls),
                   color = "grey", size = 0.1) +
      geom_polygon(aes(long, lat, group = group),
                   fill = NA, data = gusa, color = "lightgrey") +
      coord_map("bonne", parameters = 41.6) + ggthemes::theme_map() +
      scale_fill_manual(values = mycolors, na.value = "grey") +
      # scale_fill_brewer(palette = "viridis", na.value = "grey") +
      theme(plot.title = element_text(family = "Helvetica", face = "bold", size = (15)),
            legend.background = element_rect(fill = NA), 
            legend.position = "left")
  }
  plt <- plt + labs(fill=legend_title) + ggtitle(graphic_title)
  plt
}
subset_census
subset_census['pct_infected'] <- subset_census['confirmed_cases']/subset_census['total_pop']
subset_census['pct_deaths'] <- subset_census['deaths']/subset_census['total_pop']
subset_census$death_rate <- subset_census$deaths/subset_census$confirmed_cases
subset_census$county_fips_code <-as.integer(subset_census$county_fips_code)
subset_census
plot_vs_county(subset_census, "pct_infected", legend_title = "Percent Infected")
Ignoring unknown parameters: name

plot_vs_county(subset_census, "pct_infected", percentile = TRUE, banks=11, 
               legend_title = "Percentile Infected",
               graphic_title = "Percentile of Percentage of People Infected by County")

plot_vs_county(subset_census, "pct_deaths", percentile = TRUE, banks=11, 
               legend_title = "Percentile Deaths",
               graphic_title = "Percentile of Percentage of Deaths by County")

plot_vs_county(subset_census, "death_rate", percentile = TRUE, banks=11, 
               legend_title = "Percentile Mortality Rate",
               graphic_title = "Percentile of Mortality Rate by County")

plot_vs_county(subset_census, "death_rate", 
               legend_title = "Percentile Mortality Rate",
               graphic_title = "Percentile of Mortality Rate by County")
Ignoring unknown parameters: name

census_corr_cols <- colnames(subset_census)
census_corr_cols <- census_corr_cols[-1]
census_corr_cols
 [1] "confirmed_cases"    "deaths"             "median_income"      "male_pop"           "female_pop"        
 [6] "total_pop"          "median_age"         "worked_at_home"     "male_elderly_pop"   "female_elderly_pop"
[11] "pct_infected"       "pct_deaths"         "death_rate"        
subset_census
# png("./test.png", width=800, height = 800)
census_corr_cols <- colnames(subset_census)
census_corr_cols <- census_corr_cols[-1]
ggcorr(subset_census[census_corr_cols], low="red", mid="grey", high="blue", hjust= .9, size=3, 
       label = TRUE, label_size = 3, label_color = "white", layout.exp = 2) +
  ggplot2::labs(title = "Pearson Correlation of Important Variables")

ggsave("./../imgs/census_pearson.png")
Saving 7.29 x 4.51 in image

# dev.off()
global_mobility_report
country_date_pct_change <- global_mobility_report %>% select(country_region_code
                                                             | contains("date") 
                                                             | contains("percent"))
country_date_pct_change
coi_downsampled <- country_date_pct_change %>% filter(country_region_code %in% 
                                                        c("US", "CA", "NZ", "AE", "CN", "DE", "JP")) %>% 
  filter(weekdays(date) == "Monday") %>% group_by(country_region_code, date) %>% summarise_all(mean, na.rm = T) %>% arrange(country_region_code, date)
coi_downsampled
interested_cols <- c("retail_and_recreation_percent_change_from_baseline",
                     "grocery_and_pharmacy_percent_change_from_baseline",
                     "parks_percent_change_from_baseline",
                     "transit_stations_percent_change_from_baseline",
                     "workplaces_percent_change_from_baseline",
                     "residential_percent_change_from_baseline")

col_labels <- c("Average Retail and Recreation Percent Change from Baseline",
                     "Average Grocery and Pharmacy Percent Change from Baseline",
                     "Average Parks Percent Change from Baseline",
                     "Average Transit Stations Percent Change from Baseline",
                     "Average Workplaces Percent Change from Baseline",
                     "Average Residential Percent Change from Baseline")


for (i in 1:length(col_labels)){
  print(i)
  plt <- ggplot(coi_downsampled,
       aes(x=date, y=get(interested_cols[i]), group=country_region_code,
                            color=country_region_code))+
  geom_point(aes(y=rollmean(get(interested_cols[i]), k=10, na.pad=TRUE)), size=.5)+
  geom_line(aes(y=rollmean(get(interested_cols[i]), k=10, na.pad=TRUE)))+
  # geom_point(size=.5)+geom_line()+
  labs(y = col_labels[i], x = "Date", color = "Country")+
  theme(plot.title = element_text(family = "Helvetica", face = "bold", size = (15)),
        axis.title.y = element_text(size = 8))
  save_path <- paste(c("./../imgs/", interested_cols[i], ".png"), collapse = "")
  ggsave(save_path)
  print(plt)
}
[1] 1
Saving 7 x 7 in image
[1] 2
[1] 3
[1] 4
[1] 5
[1] 6

# ggplot(coi_downsampled,
#        aes(x=date, y=grocery_and_pharmacy_percent_change_from_baseline, group=country_region_code,
#                             color=country_region_code))+
#   geom_point(aes(y=rollmean(retail_and_recreation_percent_change_from_baseline, k=10, na.pad=TRUE)), size=.5)+
#   geom_line(aes(y=rollmean(retail_and_recreation_percent_change_from_baseline, k=10, na.pad=TRUE)))+
#   # geom_point(size=.5)+geom_line()+
#   labs(y = "Average Grocery and Pharmacy Percent Change from Baseline", x = "Date", color = "Country")+
#   theme(plot.title = element_text(family = "Helvetica", face = "bold", size = (15)),
#         axis.title.y = element_text(size = 8))
#   # geom_line()
tx_county_data <- tx_data %>% filter(county_name != "Statewide Unallocated")
tx_total_state_data <- tx_data %>% filter(county_name == "Statewide Unallocated")
tx_total_state_data$cumulative_deaths <- cumsum(tx_total_state_data$deaths)
tx_total_state_data$cumulative_cases <- cumsum(tx_total_state_data$confirmed_cases)
tx_county_data
tx_total_state_data

Since the above doesn’t really make sense (only 78 confirmed cases with over a thousand deaths), I am going to analyze on a per county basis and maybe that data will be more clear.

tx_by_day_based_on_county <- tx_county_data %>% 
  select(date, confirmed_cases, deaths) %>%
  group_by(date) %>% 
  summarise_all(sum, na.rm = T) %>%
  arrange(date)

# interested_cols <- c("confirmed_cases", "deaths")
# col_labels <- c("Total Cases", "Total Deaths")
# 
# for (i in 1:length(col_labels)){
#   print(i)
#   title <- paste(c("Texas ", col_labels[i]), collapse = "")
#   plt <- ggplot(tx_by_day_based_on_county,
#        aes(x=date, y=get(interested_cols[i])))+
#   # geom_point(aes(y=rollmean(get(interested_cols[i]), k=10, na.pad=TRUE)), size=.5)+
#   # geom_line(aes(y=rollmean(get(interested_cols[i]), k=10, na.pad=TRUE)))+
#   # geom_point(size=.5)+geom_line()+
#     geom_line(color)+
#   labs(y = col_labels[i], x = "Date", title = title)
#   # theme(plot.title = element_text(family = "Helvetica", face = "bold", size = (15)),
#   #       axis.title.y = element_text(size = 8))
#   # save_path <- paste(c("./../imgs/", interested_cols[i], ".png"), collapse = "")
#   # ggsave(save_path)
#   print(plt)
# }
tx_by_day_based_on_county
install.packages("ggrepel")
trying URL 'https://cran.rstudio.com/bin/macosx/contrib/4.0/ggrepel_0.9.1.tgz'
Content type 'application/x-gzip' length 702306 bytes (685 KB)
==================================================
downloaded 685 KB

The downloaded binary packages are in
    /var/folders/2t/zk2m3vcj2_51x1r2p3cbnt9r0000gn/T//RtmpNDvNE3/downloaded_packages
library(ggrepel)
tx_by_day_based_on_county %>% pivot_longer(!date, names_to = "type", values_to = "count")
# t <- tibble("Max" = c(34378, 2248927), "date" = c("2021-01-25", "2021-01-25"),
#             "type" = c("deaths", "confirmed_cases"))
# t$date <- as.Date(t$date)
# t 

data_ends <- tx_by_day_based_on_county %>% pivot_longer(!date, names_to = "type", values_to = "count") %>% 
  group_by(type) %>% 
  top_n(1, count) 
data_ends
NA
library(scales)
# png("./../imgs/texas_covid_cases_total.png", width = 800, height = 800)
# tx_by_day_based_on_county %>% pivot_longer(!date, names_to = "type", values_to = "count")
ggplot(tx_by_day_based_on_county %>% pivot_longer(!date, names_to = "type", values_to = "count"),
       aes(x=date, y=count, group=type))+
         geom_line(aes(color=type))+
  # scale_y_continuous(trans = "log10",
  #                    labels = trans_breaks('log10', math_format(10^.x)))+
  scale_color_manual(labels = c("Confirmed Cases", "Deaths"), values = c("confirmed_cases"="blue",
                                                                         "deaths"="red"))+
  labs(y = "Total Persons", x = "Date", color = "")+
  geom_text_repel(aes(label = count), data = data_ends, size=3)+
  # scale_y_continuous(sec.axis = sec_axis(~ ., breaks = data_ends))+
  theme(plot.title = element_text(family = "Helvetica", face = "bold", size = (15)))+
  ggtitle("Texas COVID-19 Cases")
  
# plt+ 
# ggplot(t, 
#              aes(x=Date, y= Max))+
#   geom_point()
# plt + geom_text_repel(aes(label = Max), data = t, fontface="plain", color="black",
#                   size=3)
# dev.off()

ggsave("./../imgs/texas_covid_cases_total.png")
Saving 7.29 x 4.51 in image

  # scale_y_log10()
         # labs(y = "Total Persons", x = "Date"))

# )
# 
# plt <- ggplot(coi_downsampled,
#        aes(x=date, y=get(interested_cols[i]), group=country_region_code,
#                             color=country_region_code))+
#   geom_point(aes(y=rollmean(get(interested_cols[i]), k=10, na.pad=TRUE)), size=.5)+
#   geom_line(aes(y=rollmean(get(interested_cols[i]), k=10, na.pad=TRUE)))+
#   # geom_point(size=.5)+geom_line()+
#   labs(y = col_labels[i], x = "Date", color = "Country")+
#   theme(plot.title = element_text(family = "Helvetica", face = "bold", size = (15)),
#         axis.title.y = element_text(size = 8))
#   save_path <- paste(c("./../imgs/", interested_cols[i], ".png"), collapse = "")
#   ggsave(save_path)
#   print(plt)
tx_county_data
subset_census

tx_state <- map_data("state") %>% subset(region == "texas")
tx_county_map_data <- map_data("county") %>% subset(region == "texas")

tx_state
tx_county_map_data

gcounty <- map_data("county")
# 
# fipstab <-
#       transmute(maps::county.fips, fips, county = sub(":.*", "", polyname)) %>%
#       unique() %>%
#       separate(county, c("region", "subregion"), sep = ",")

# Format with subregions
fipstab <-
  transmute(maps::county.fips, fips, county = sub(":.*", "", polyname)) %>%
  unique() %>%
  separate(county, c("region", "subregion"), sep = ",")
  
  # # Combine in desired order (NA for missing)
  # gcounty <- left_join(gcounty, fipstab, c("region", "subregion"))


tx_geo_data <- left_join(gcounty, fipstab, c("region", "subregion")) %>%
  left_join(subset_census, c("fips" = "county_fips_code")) %>% filter(region == "texas") %>%
  unique()

tx_geo_data$dinfect_pcls <- cut(100 * percent_rank(tx_geo_data$pct_infected), seq(0, 100, len = 11),
                        include.lowest = TRUE)
tx_geo_data$deaths_pcls <- cut(100 * percent_rank(tx_geo_data$pct_deaths), seq(0, 100, len = 11),
                        include.lowest = TRUE)
tx_geo_data$death_rate_pcls <- cut(100 * percent_rank(tx_geo_data$death_rate), seq(0, 100, len = 11),
                        include.lowest = TRUE)

tx_geo_data


# 
# # Lowercase
# tx_county_data$county_name <- tolower(tx_county_data$county_name)
# 
# # Remove ' county'
# tx_county_data$county_name <- sub("\\s*county\\b.*", "", tx_county_data$county_name)
# tx_county_data
# 
# # Get max confirmed cases and deaths
# tx_county_data
# 
# 
# # # Join the data with state geo info
# # tx_geo_data <- left_join(tx_county_map_data, tx_county_data, by = c("subregion" = "county_name"))
# # tx_geo_data

mycolors <- colorRampPalette(brewer.pal(9, "Reds"))(11)

ggplot(tx_geo_data)+
  coord_map() + ggthemes::theme_map()+
  geom_polygon(aes(long, lat, group = group, fill=death_rate_pcls))+
  scale_fill_manual(values = mycolors, na.value = "grey") +
  theme(plot.title = element_text(family = "Helvetica", face = "bold", size = (15)), legend.position = "left")+
  #       legend.background = element_rect(fill = NA),
        # legend.position = "left")+
  labs(fill="Percentile") + ggtitle("Texas County Mortality Rate Percentiles")

ggsave("./../imgs/texas_county_mortality_percentiles.png")
Saving 7.29 x 4.51 in image

# ggplot(tx_geo_data) +
#       geom_polygon(aes(long, lat, group = group, fill = death_rate_pcls),
#                    color = "grey", size = 0.1) +
#       # geom_polygon(aes(long, lat, group = group),
#       #              fill = NA, data = gusa, color = "lightgrey") +
#       coord_map("bonne", parameters = 41.6) + ggthemes::theme_map() +
#       scale_fill_manual(values = mycolors, na.value = "grey") +
#       # scale_fill_brewer(palette = "viridis", na.value = "grey") +
#       theme(plot.title = element_text(family = "Helvetica", face = "bold", size = (15)),
#             legend.background = element_rect(fill = NA),
#             legend.position = "left")



# if (percentile == TRUE){
#     plt <- ggplot(gcounty_pop) +
#       geom_polygon(aes(long, lat, group = group, fill = pcls),
#                    color = "grey", size = 0.1) +
#       geom_polygon(aes(long, lat, group = group),
#                    fill = NA, data = gusa, color = "lightgrey") +
#       coord_map("bonne", parameters = 41.6) + ggthemes::theme_map() +
#       scale_fill_manual(values = mycolors, na.value = "grey") +
#       # scale_fill_brewer(palette = "viridis", na.value = "grey") +
#       theme(plot.title = element_text(family = "Helvetica", face = "bold", size = (15)),
#             legend.background = element_rect(fill = NA), 
#             legend.position = "left")
    

# plt <- ggplot(gcounty_pop) +
#       geom_polygon(aes(long, lat, group = group, fill = dinfect_pcls),
#                    color = "grey", size = 0.1) +
#       geom_polygon(aes(long, lat, group = group),
#                    fill = NA, data = gusa, color = "lightgrey") +
#       coord_map("bonne", parameters = 41.6) + ggthemes::theme_map() +
#       scale_fill_manual(values = mycolors, na.value = "grey") +
#       # scale_fill_brewer(palette = "viridis", na.value = "grey") +
#       theme(plot.title = element_text(family = "Helvetica", face = "bold", size = (15)),
#             legend.background = element_rect(fill = NA),
#             legend.position = "left")

# ggplot(tx_geo_data) +
#          coord_map() + 
#   ggthemes::theme_map()+
#   geom_polygon(aes(long, lat, group = subregion, fill = confirmed_cases))
# pc_cont_iowa <- geom_polygon(aes(long, lat, group = group, fill = pchange),
#                              color = "grey", size = 0.2)
data_ends <- dallas_data %>% pivot_longer(!date, names_to = "type", values_to = "count") %>% 
  group_by(type) %>% 
  top_n(1, count) 
data_ends
# dallas_data <- tx_county_data %>% filter(county_name == "dallas") 
dallas_data <- tx_county_data %>% filter(county_name == "Dallas County") %>% 
  select(date, confirmed_cases, deaths)

data_ends <- dallas_data %>% pivot_longer(!date, names_to = "type", values_to = "count") %>% 
  group_by(type) %>% 
  top_n(1, count) 

ggplot(dallas_data %>% pivot_longer(!date, names_to = "type", values_to = "count"),
       aes(x=date, y=count, group=type))+
         geom_line(aes(color=type))+
  # scale_y_continuous(trans = "log10", labels = trans_breaks("log10", math_format(10^.x)))+
  # scale_y_log10(breaks=c(100, 300, 500, 1000, 3000, 5000, 10000, 30000, 50000, 100000, 300000),
  #               labels=c('100', '300', '500', '1000', '3000', '5000', '10000', '30000', '50000', '100000', '300000'))+
  scale_color_manual(labels = c("Confirmed Cases", "Deaths"), values = c("confirmed_cases"="blue",
                                                                         "deaths"="red"))+
  labs(y = "Total Persons", x = "Date", color = "")+
  geom_text_repel(aes(label = count), data = data_ends, size=3)+
  theme(plot.title = element_text(family = "Helvetica", face = "bold", size = (15)))+
  ggtitle("Dallas COVID-19 Cases")
  ggsave("./../imgs/dallas_covid_cases_total.png")
Saving 7.29 x 4.51 in image

sgcounty <- map_data("state")

# Format with subregions
fipstab <-
  transmute(maps::county.fips, fips, county = sub(":.*", "", polyname)) %>%
  unique() %>%
  separate(county, c("region", "subregion"), sep = ",")

us_geo_data <- left_join(gcounty, fipstab, c("region", "subregion")) %>%
  left_join(subset_census, c("fips" = "county_fips_code")) %>%
  unique() %>% select(long, lat, region, subregion, group, confirmed_cases, deaths, median_income, 
                      male_pop, female_pop, total_pop, median_age,
                      worked_at_home)
# us_geo_data

# Get the total cases by state
state_data_breakdown <- us_geo_data %>% 
  drop_na() %>% select(region, subregion, confirmed_cases, deaths, median_income, 
                      male_pop, female_pop, total_pop, median_age,
                      worked_at_home) %>% unique() %>%
  group_by(region) %>% select_if(is.numeric) %>%
  summarise_all(sum)

state_data_breakdown$pct_deaths <- state_data_breakdown$deaths/state_data_breakdown$total_pop
state_data_breakdown$pct_infect <- state_data_breakdown$confirmed_cases/state_data_breakdown$total_pop
state_data_breakdown$death_rate <- state_data_breakdown$deaths/state_data_breakdown$confirmed_cases

print(state_data_breakdown %>% arrange(death_rate, decreasing=T))

state_geo_data <- us_geo_data %>% select(long, lat, region, group) %>% left_join(state_data_breakdown,
                                                        by = "region")

state_geo_data

# ggplot(tx_by_day_based_on_county %>% pivot_longer(!date, names_to = "type", values_to = "count"),
#        aes(x=date, y=count, group=type, color = type))+
#          geom_line()+
#   scale_y_continuous(trans = "log10",
#                      labels = trans_breaks('log10', math_format(10^.x)))+
#   scale_color_manual(labels = c("Confirmed Cases", "Deaths"), values = c("confirmed_cases"="blue",
#                                                                          "deaths"="red"))+
#   labs(y = "Total Persons", x = "Date", color = "")+
#   theme(plot.title = element_text(family = "Helvetica", face = "bold", size = (15)))+
#   ggtitle("US COVID-19 Cases")
  # ggsave("./../imgs/texas_covid_cases_total.png")
# state_geo_data$state_group <- factor
state_geo_data$state_group <- factor(state_geo_data$region) 
state_geo_data$state_group <- as.numeric(state_geo_data$state_group)
state_geo_data
state_data_breakdown
# http://homepage.stat.uiowa.edu/~luke/classes/STAT4580-2020/maps.html

library(scales)
sp <- select(state_data_breakdown, region = region, death_rate)
gusa <- map_data("state")

gusa_pop <- left_join(gusa, sp, "region")
gusa_pop

ggplot(gusa_pop) +
    geom_polygon(aes(long, lat, group = group, fill = death_rate), color="grey") +
    coord_map("bonne", parameters = 41.6) +
    ggthemes::theme_map()+
  theme(plot.title = element_text(family = "Helvetica", face = "bold", size = (15)))+
  scale_fill_gradient(labels = percent)+
  ggtitle("Mortality Rate by State")+
  labs(fill="Mortality Rate")

ggsave("./../imgs/mortality_rate_by_state.png")
Saving 7.29 x 4.51 in image

tx_data
cases_plus_census
tx_county_data
# Get the first occurrences of covid case after first tx case
tx_first_cases_by_county <- tx_county_data %>% filter(confirmed_cases > 0) %>% 
  group_by(county_name) %>%
  arrange(date) %>% slice_min(order_by = date, n = 1) %>% 
  select(county_fips_code, county_name, date)

first_day_in_tx <- min(tx_first_cases_by_county$date)

tx_first_cases_by_county <- tx_first_cases_by_county %>% 
  mutate(days_from_first_tx_case = date - first_day_in_tx) %>%
  mutate(county_fips_code = as.integer(county_fips_code))

tx_first_cases_by_county
tx_first_cases_by_county %>% filter(days_from_first_tx_case == time_length(0, "days"))
tx_state <- map_data("state") %>% subset(region == "texas")
tx_county_map_data <- map_data("county") %>% subset(region == "texas")

gcounty <- map_data("county")

# Format with subregions
fipstab <-
  transmute(maps::county.fips, fips, county = sub(":.*", "", polyname)) %>%
  unique() %>%
  separate(county, c("region", "subregion"), sep = ",") %>% filter(region == "texas")


fipstab
tx_geo_days <- left_join(gcounty, fipstab, c("region", "subregion")) %>%
  left_join(tx_first_cases_by_county, c("fips" = "county_fips_code")) %>% filter(region == "texas") %>%
  unique()

tx_geo_days
# 
# tx_geo_data$dinfect_pcls <- cut(100 * percent_rank(tx_geo_data$pct_infected), seq(0, 100, len = 11),
#                         include.lowest = TRUE)
# tx_geo_data$deaths_pcls <- cut(100 * percent_rank(tx_geo_data$pct_deaths), seq(0, 100, len = 11),
#                         include.lowest = TRUE)
# tx_geo_data$death_rate_pcls <- cut(100 * percent_rank(tx_geo_data$death_rate), seq(0, 100, len = 11),
#                         include.lowest = TRUE)
# 
# tx_geo_data

# # Lowercase
# tx_county_data$county_name <- tolower(tx_county_data$county_name)
# 
# # Remove ' county'
# tx_county_data$county_name <- sub("\\s*county\\b.*", "", tx_county_data$county_name)
# tx_county_data
ggplot(tx_geo_days %>% mutate(days_from_first_tx_case = as.integer(days_from_first_tx_case))) +
  coord_map() + ggthemes::theme_map()+
  geom_polygon(aes(long, lat, group = group, fill=days_from_first_tx_case))+
  # scale_fill_manual(values = mycolors, na.value = "grey") +
  theme(plot.title = element_text(family = "Helvetica", face = "bold", size = (15)), legend.position = "left")+
  #       legend.background = element_rect(fill = NA),
        # legend.position = "left")+
  labs(fill="Days from First TX Case") + ggtitle("Texas Spread of COVID-19")+
  # scale_fill_manual(low="red", mid="grey", high="blue")
  scale_fill_gradient(low = "grey", high = "red", na.value = NA)
ggsave("./../imgs/tx_spread_days.png")
Saving 7.29 x 4.51 in image

  # scale_fill_gradient(low="red", mid="grey", high="blue")
  # scale_fill_gradientn()
  # scale_colour_gradient2()
  
LS0tCnRpdGxlOiAiQ2xlYW5lZCBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKYGBge3J9CmxpYnJhcnkoYmVlc3dhcm0pCmxpYnJhcnkobmFuaWFyKQpsaWJyYXJ5KHpvbykKIyBpbnN0YWxsLnBhY2thZ2VzKCJ6b28iKQpsaWJyYXJ5KGphbml0b3IpCmxpYnJhcnkoZHBseXIpCiMgaW5zdGFsbC5wYWNrYWdlcygiR0dhbGx5IikKIyBsaWJyYXJ5KHNldHMpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoR0dhbGx5KSAjIGZvciBnZ3BhaXJzCmxpYnJhcnkobHVicmlkYXRlKQojIGluc3RhbGwucGFja2FnZXMoIm1hcHMiKQojIGxpYnJhcnkobWFwcykKYGBgCgpgYGB7cn0KbG9hZF9maWxlIDwtIGZ1bmN0aW9uKGZpbGVfcGF0aCl7CiAgcmVhZF9jc3YoZmlsZV9wYXRoKQp9Cgp0eF9kYXRhIDwtIGxvYWRfZmlsZSgiLi8uLi9kYXRhL0NPVklELTE5X2Nhc2VzX1RYLmNzdiIpCmdsb2JhbF9tb2JpbGl0eV9yZXBvcnQgPC0gbG9hZF9maWxlKCIuLy4uL2RhdGEvR2xvYmFsX01vYmlsaXR5X1JlcG9ydC5jc3YiKQpjYXNlc19wbHVzX2NlbnN1cyA8LSBsb2FkX2ZpbGUoIi4vLi4vZGF0YS9DT1ZJRC0xOV9jYXNlc19wbHVzX2NlbnN1cy5jc3YiKQpgYGAKYGBge3J9CmNvbHNfa2VlcCA8LSBjKCJjb3VudHlfZmlwc19jb2RlIiwgImNvbmZpcm1lZF9jYXNlcyIsICJkZWF0aHMiLCAibWVkaWFuX2luY29tZSIsICJtYWxlX3BvcCIsICJmZW1hbGVfcG9wIiwgInRvdGFsX3BvcCIsICJtZWRpYW5fYWdlIiwgIndvcmtlZF9hdF9ob21lIiwgIm1hbGVfNjVfdG9fNjYiLCAibWFsZV82N190b182OSIsIAogICAgICAgICAgICAgICAibWFsZV83MF90b183NCIsICJtYWxlXzc1X3RvXzc5IiwgIm1hbGVfODBfdG9fODQiLAogICAgICAgICAgICAgICAibWFsZV84NV9hbmRfb3ZlciIsICJmZW1hbGVfNjVfdG9fNjYiLCAiZmVtYWxlXzY3X3RvXzY5IiwgCiAgICAgICAgICAgICAgICJmZW1hbGVfNzBfdG9fNzQiLCAiZmVtYWxlXzc1X3RvXzc5IiwgImZlbWFsZV84MF90b184NCIsCiAgICAgICAgICAgICAgICJmZW1hbGVfODVfYW5kX292ZXIiKQpzdWJzZXRfY2Vuc3VzIDwtIGNhc2VzX3BsdXNfY2Vuc3VzW2NvbHNfa2VlcF0KCnN1YnNldF9jZW5zdXMkbWFsZV9lbGRlcmx5X3BvcCA8LSBzdWJzZXRfY2Vuc3VzICU+JSBzZWxlY3QoYygibWFsZV82NV90b182NiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAibWFsZV82N190b182OSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIm1hbGVfNzBfdG9fNzQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIm1hbGVfNzVfdG9fNzkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIm1hbGVfODBfdG9fODQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIm1hbGVfODVfYW5kX292ZXIiKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgJT4lIHJvd1N1bXMoKQoKc3Vic2V0X2NlbnN1cyRmZW1hbGVfZWxkZXJseV9wb3AgPC0gc3Vic2V0X2NlbnN1cyAlPiUgc2VsZWN0KGMoImZlbWFsZV82NV90b182NiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZmVtYWxlXzY3X3RvXzY5IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZmVtYWxlXzcwX3RvXzc0IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJmZW1hbGVfNzVfdG9fNzkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImZlbWFsZV84MF90b184NCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZmVtYWxlXzg1X2FuZF9vdmVyIikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICU+JSByb3dTdW1zKCkKCmNvbHNfa2VlcCA8LSBjKCJjb3VudHlfZmlwc19jb2RlIiwgImNvbmZpcm1lZF9jYXNlcyIsICJkZWF0aHMiLCAibWVkaWFuX2luY29tZSIsCiAgICAgICAgICAgICAgICJtYWxlX3BvcCIsICJmZW1hbGVfcG9wIiwgInRvdGFsX3BvcCIsICJtZWRpYW5fYWdlIiwKICAgICAgICAgICAgICAgIndvcmtlZF9hdF9ob21lIiwgIm1hbGVfZWxkZXJseV9wb3AiLCAiZmVtYWxlX2VsZGVybHlfcG9wIikKc3Vic2V0X2NlbnN1cyA8LSBzdWJzZXRfY2Vuc3VzW2NvbHNfa2VlcF0Kc3Vic2V0X2NlbnN1cwoKIyBjb2xzX2tlZXAgPC0gYygiZGF0ZSIsICJyZXRhaWxfYW5kX3JlY3JlYXRpb25fcGVyY2VudF9jaGFuZ2VfZnJvbV9iYXNlbGluZSIsICJncm9jZXJ5X2FuZF9waGFybWFjeV9wZXJjZW50X2NoYW5nZV9mcm9tX2Jhc2VsaW5lIiwgInBhcmtzX3BlcmNlbnRfY2hhbmdlX2Zyb21fYmFzZWxpbmUiLCAidHJhbnNpdF9zdGF0aW9uc19wZXJjZW50X2NoYW5nZV9mcm9tX2Jhc2VsaW5lIiwgIndvcmtwbGFjZXNfcGVyY2VudF9jaGFuZ2VfZnJvbV9iYXNlbGluZSIsICJyZXNpZGVudGlhbF9wZXJjZW50X2NoYW5nZV9mcm9tX2Jhc2VsaW5lIikKIyBzdWJzZXRfbW9iaWxpdHkgPC0gZ2xvYmFsX21vYmlsaXR5X3JlcG9ydFtjb2xzX2tlZXBdCiMgZ2xvCiMgc3Vic2V0X21vYmlsaXR5JGRhdGUgPC0gYXMuRGF0ZShzdWJzZXRfbW9iaWxpdHkkZGF0ZSwgZm9ybWF0PSIlWS0lbS0lZCIpCmBgYAoKYGBge3J9CiMgZ2xvYmFsX21vYmlsaXR5X3JlcG9ydAp2aXNfbWlzcyhnbG9iYWxfbW9iaWxpdHlfcmVwb3J0LCBzb3J0X21pc3MgPSBULCB3YXJuX2xhcmdlX2RhdGE9IEYpCmBgYAoKCmBgYHtyfQp2aXNfbWlzcyh0eF9kYXRhLCBzb3J0X21pc3MgPSBULCB3YXJuX2xhcmdlX2RhdGE9IEYpCnZpc19taXNzKHN1YnNldF9jZW5zdXMsIHNvcnRfbWlzcyA9IFQsIHdhcm5fbGFyZ2VfZGF0YSA9IEYpCmBgYAoKYGBge3J9CmxpYnJhcnkoUkNvbG9yQnJld2VyKQpwbG90X3ZzX2NvdW50eSA8LSBmdW5jdGlvbihkZiwgY29sX3ZhbCwgcGVyY2VudGlsZT1GQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlwc190aXRsZT0iY291bnR5X2ZpcHNfY29kZSIsIGJhbmtzPTYsIAogICAgICAgICAgICAgICAgICAgICAgICAgICBsZWdlbmRfdGl0bGU9IiIsIGdyYXBoaWNfdGl0bGU9IiIpewogICMgU3Vic2V0IGZvciBzcGVlZCAKICBkZiA8LSBkZltjKGZpcHNfdGl0bGUsIGNvbF92YWwpXQogIAogICMgR2V0IGNvdW50eSBkYXRhCiAgZ2NvdW50eSA8LSBnZ3Bsb3QyOjptYXBfZGF0YSgiY291bnR5IikKICAjIFVTQSBtYXAgZGF0YQogIGd1c2EgPC0gbWFwX2RhdGEoInN0YXRlIikKICAKICBpZiAoYmFua3MgPiA5KXsKICAgIG15Y29sb3JzIDwtIGNvbG9yUmFtcFBhbGV0dGUoYnJld2VyLnBhbCg5LCAiUmVkcyIpKShiYW5rcykKICB9CiAgCiAgIyBGb3JtYXQgd2l0aCBzdWJyZWdpb25zCiAgZmlwc3RhYiA8LQogICAgICB0cmFuc211dGUobWFwczo6Y291bnR5LmZpcHMsIGZpcHMsIGNvdW50eSA9IHN1YigiOi4qIiwgIiIsIHBvbHluYW1lKSkgJT4lCiAgICAgIHVuaXF1ZSgpICU+JQogICAgICBzZXBhcmF0ZShjb3VudHksIGMoInJlZ2lvbiIsICJzdWJyZWdpb24iKSwgc2VwID0gIiwiKQogIAogICMgQ29tYmluZSBpbiBkZXNpcmVkIG9yZGVyIChOQSBmb3IgbWlzc2luZykKICBnY291bnR5IDwtIGxlZnRfam9pbihnY291bnR5LCBmaXBzdGFiLCBjKCJyZWdpb24iLCAic3VicmVnaW9uIikpCgoKICBkaXMgPC0gZGYKICBkaXMkcnByb3AgPC0gcmFuayhkZltjb2xfdmFsXSkKICBkaXMkcGNscyA8LSBjdXQoMTAwICogcGVyY2VudF9yYW5rKGRmW2NvbF92YWxdKSwgc2VxKDAsIDEwMCwgbGVuID0gYmFua3MpLAogICAgICAgICAgICAgICAgICAgICAgICBpbmNsdWRlLmxvd2VzdCA9IFRSVUUpCgogICMgTWlzc2luZyBkYXRhCiAgYW50aV9qb2luKGdjb3VudHksIGRpcywgYnkgPSBjKCJmaXBzIiA9IGZpcHNfdGl0bGUpKSAlPiUKICAgIHNlbGVjdChyZWdpb24sIHN1YnJlZ2lvbikgJT4lCiAgICB1bmlxdWUoKQogIGdjb3VudHlfcG9wIDwtIGxlZnRfam9pbihnY291bnR5LCBkaXMsIGJ5ID0gYygiZmlwcyIgPSBmaXBzX3RpdGxlKSkKICBmaWxsX3ZhbHMgPC0gZ2NvdW50eV9wb3BbY29sX3ZhbF0KCiAgIyBQbG90CiAgaWYgKGxlZ2VuZF90aXRsZSA9PSAiIil7CiAgICBsZWdlbmRfdGl0bGUgPC0gY29sX3ZhbAogIH0KCiAgaWYgKHBlcmNlbnRpbGUgPT0gRkFMU0UpewogICAgIyBuYW1lcyhnY291bnR5X3BvcClbbmFtZXMoZ2NvdW50eV9wb3ApID09IGNvbF92YWxdIDwtICJjb2xfb2ZfaW50ZXJlc3QiCiAgICBwbHQgPC0gZ2dwbG90KGdjb3VudHlfcG9wKSArCiAgICAgIGdlb21fcG9seWdvbihhZXMobG9uZywgbGF0LCBncm91cCA9IGdyb3VwLCBmaWxsID0gZ2V0KGNvbF92YWwpKSwKICAgICAgICAgICAgICAgICAgIGNvbG9yID0gImdyZXkiLCBzaXplID0gMC4xLCBuYW1lPSJQZXJjZW50IEluZmVjdGVkIikgKwogICAgICBnZW9tX3BvbHlnb24oYWVzKGxvbmcsIGxhdCwgZ3JvdXAgPSBncm91cCksCiAgICAgICAgICAgICAgICAgICBmaWxsID0gTkEsIGRhdGEgPSBndXNhLCBjb2xvciA9ICJsaWdodGdyZXkiKSArCiAgICAgIGNvb3JkX21hcCgiYm9ubmUiLCBwYXJhbWV0ZXJzID0gNDEuNikgKyBnZ3RoZW1lczo6dGhlbWVfbWFwKCkrCiAgICAgIHNjYWxlX2ZpbGxfZ3JhZGllbnQyKCkKICAgICAgICMgc2NhbGVfZmlsbF9ncmFkaWVudChsb3cgPSAid2hpdGUiLCBoaWdoID0gInJlZCIsIG5hLnZhbHVlID0gImdyZXkiKQogICAgICAjIHNjYWxlX2ZpbGxfZ3JhZGllbnRuKGNvbG91cnMgPSB0ZXJyYWluLmNvbG9ycygxMCkpCiAgfQoKICBpZiAocGVyY2VudGlsZSA9PSBUUlVFKXsKICAgIHBsdCA8LSBnZ3Bsb3QoZ2NvdW50eV9wb3ApICsKICAgICAgZ2VvbV9wb2x5Z29uKGFlcyhsb25nLCBsYXQsIGdyb3VwID0gZ3JvdXAsIGZpbGwgPSBwY2xzKSwKICAgICAgICAgICAgICAgICAgIGNvbG9yID0gImdyZXkiLCBzaXplID0gMC4xKSArCiAgICAgIGdlb21fcG9seWdvbihhZXMobG9uZywgbGF0LCBncm91cCA9IGdyb3VwKSwKICAgICAgICAgICAgICAgICAgIGZpbGwgPSBOQSwgZGF0YSA9IGd1c2EsIGNvbG9yID0gImxpZ2h0Z3JleSIpICsKICAgICAgY29vcmRfbWFwKCJib25uZSIsIHBhcmFtZXRlcnMgPSA0MS42KSArIGdndGhlbWVzOjp0aGVtZV9tYXAoKSArCiAgICAgIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IG15Y29sb3JzLCBuYS52YWx1ZSA9ICJncmV5IikgKwogICAgICAjIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGUgPSAidmlyaWRpcyIsIG5hLnZhbHVlID0gImdyZXkiKSArCiAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gIkhlbHZldGljYSIsIGZhY2UgPSAiYm9sZCIsIHNpemUgPSAoMTUpKSwKICAgICAgICAgICAgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9IE5BKSwgCiAgICAgICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJsZWZ0IikKICB9CiAgcGx0IDwtIHBsdCArIGxhYnMoZmlsbD1sZWdlbmRfdGl0bGUpICsgZ2d0aXRsZShncmFwaGljX3RpdGxlKQogIHBsdAp9CmBgYAoKYGBge3J9CnN1YnNldF9jZW5zdXMKYGBgCgpgYGB7cn0Kc3Vic2V0X2NlbnN1c1sncGN0X2luZmVjdGVkJ10gPC0gc3Vic2V0X2NlbnN1c1snY29uZmlybWVkX2Nhc2VzJ10vc3Vic2V0X2NlbnN1c1sndG90YWxfcG9wJ10Kc3Vic2V0X2NlbnN1c1sncGN0X2RlYXRocyddIDwtIHN1YnNldF9jZW5zdXNbJ2RlYXRocyddL3N1YnNldF9jZW5zdXNbJ3RvdGFsX3BvcCddCnN1YnNldF9jZW5zdXMkZGVhdGhfcmF0ZSA8LSBzdWJzZXRfY2Vuc3VzJGRlYXRocy9zdWJzZXRfY2Vuc3VzJGNvbmZpcm1lZF9jYXNlcwpzdWJzZXRfY2Vuc3VzJGNvdW50eV9maXBzX2NvZGUgPC1hcy5pbnRlZ2VyKHN1YnNldF9jZW5zdXMkY291bnR5X2ZpcHNfY29kZSkKc3Vic2V0X2NlbnN1cwpgYGAKYGBge3J9CnBsb3RfdnNfY291bnR5KHN1YnNldF9jZW5zdXMsICJwY3RfaW5mZWN0ZWQiLCBsZWdlbmRfdGl0bGUgPSAiUGVyY2VudCBJbmZlY3RlZCIpCnBsb3RfdnNfY291bnR5KHN1YnNldF9jZW5zdXMsICJwY3RfaW5mZWN0ZWQiLCBwZXJjZW50aWxlID0gVFJVRSwgYmFua3M9MTEsIAogICAgICAgICAgICAgICBsZWdlbmRfdGl0bGUgPSAiUGVyY2VudGlsZSBJbmZlY3RlZCIsCiAgICAgICAgICAgICAgIGdyYXBoaWNfdGl0bGUgPSAiUGVyY2VudGlsZSBvZiBQZXJjZW50YWdlIG9mIFBlb3BsZSBJbmZlY3RlZCBieSBDb3VudHkiKQpwbG90X3ZzX2NvdW50eShzdWJzZXRfY2Vuc3VzLCAicGN0X2RlYXRocyIsIHBlcmNlbnRpbGUgPSBUUlVFLCBiYW5rcz0xMSwgCiAgICAgICAgICAgICAgIGxlZ2VuZF90aXRsZSA9ICJQZXJjZW50aWxlIERlYXRocyIsCiAgICAgICAgICAgICAgIGdyYXBoaWNfdGl0bGUgPSAiUGVyY2VudGlsZSBvZiBQZXJjZW50YWdlIG9mIERlYXRocyBieSBDb3VudHkiKQpwbG90X3ZzX2NvdW50eShzdWJzZXRfY2Vuc3VzLCAiZGVhdGhfcmF0ZSIsIHBlcmNlbnRpbGUgPSBUUlVFLCBiYW5rcz0xMSwgCiAgICAgICAgICAgICAgIGxlZ2VuZF90aXRsZSA9ICJQZXJjZW50aWxlIE1vcnRhbGl0eSBSYXRlIiwKICAgICAgICAgICAgICAgZ3JhcGhpY190aXRsZSA9ICJQZXJjZW50aWxlIG9mIE1vcnRhbGl0eSBSYXRlIGJ5IENvdW50eSIpCnBsb3RfdnNfY291bnR5KHN1YnNldF9jZW5zdXMsICJkZWF0aF9yYXRlIiwgCiAgICAgICAgICAgICAgIGxlZ2VuZF90aXRsZSA9ICJQZXJjZW50aWxlIE1vcnRhbGl0eSBSYXRlIiwKICAgICAgICAgICAgICAgZ3JhcGhpY190aXRsZSA9ICJQZXJjZW50aWxlIG9mIE1vcnRhbGl0eSBSYXRlIGJ5IENvdW50eSIpCmBgYApgYGB7cn0KY2Vuc3VzX2NvcnJfY29scyA8LSBjb2xuYW1lcyhzdWJzZXRfY2Vuc3VzKQpjZW5zdXNfY29ycl9jb2xzIDwtIGNlbnN1c19jb3JyX2NvbHNbLTFdCmNlbnN1c19jb3JyX2NvbHMKYGBgCgpgYGB7cn0Kc3Vic2V0X2NlbnN1cwpgYGAKCmBgYHtyfQojIHBuZygiLi90ZXN0LnBuZyIsIHdpZHRoPTgwMCwgaGVpZ2h0ID0gODAwKQpjZW5zdXNfY29ycl9jb2xzIDwtIGNvbG5hbWVzKHN1YnNldF9jZW5zdXMpCmNlbnN1c19jb3JyX2NvbHMgPC0gY2Vuc3VzX2NvcnJfY29sc1stMV0KZ2djb3JyKHN1YnNldF9jZW5zdXNbY2Vuc3VzX2NvcnJfY29sc10sIGxvdz0icmVkIiwgbWlkPSJncmV5IiwgaGlnaD0iYmx1ZSIsIGhqdXN0PSAuOSwgc2l6ZT0zLCAKICAgICAgIGxhYmVsID0gVFJVRSwgbGFiZWxfc2l6ZSA9IDMsIGxhYmVsX2NvbG9yID0gIndoaXRlIiwgbGF5b3V0LmV4cCA9IDIpICsKICBnZ3Bsb3QyOjpsYWJzKHRpdGxlID0gIlBlYXJzb24gQ29ycmVsYXRpb24gb2YgSW1wb3J0YW50IFZhcmlhYmxlcyIpCgpnZ3NhdmUoIi4vLi4vaW1ncy9jZW5zdXNfcGVhcnNvbi5wbmciKQoKIyBkZXYub2ZmKCkKYGBgCmBgYHtyfQpnbG9iYWxfbW9iaWxpdHlfcmVwb3J0CmBgYAoKCmBgYHtyfQpjb3VudHJ5X2RhdGVfcGN0X2NoYW5nZSA8LSBnbG9iYWxfbW9iaWxpdHlfcmVwb3J0ICU+JSBzZWxlY3QoY291bnRyeV9yZWdpb25fY29kZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfCBjb250YWlucygiZGF0ZSIpIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfCBjb250YWlucygicGVyY2VudCIpKQpjb3VudHJ5X2RhdGVfcGN0X2NoYW5nZQpgYGAKYGBge3J9CmNvaV9kb3duc2FtcGxlZCA8LSBjb3VudHJ5X2RhdGVfcGN0X2NoYW5nZSAlPiUgZmlsdGVyKGNvdW50cnlfcmVnaW9uX2NvZGUgJWluJSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjKCJVUyIsICJDQSIsICJOWiIsICJBRSIsICJDTiIsICJERSIsICJKUCIpKSAlPiUgCiAgZmlsdGVyKHdlZWtkYXlzKGRhdGUpID09ICJNb25kYXkiKSAlPiUgZ3JvdXBfYnkoY291bnRyeV9yZWdpb25fY29kZSwgZGF0ZSkgJT4lIHN1bW1hcmlzZV9hbGwobWVhbiwgbmEucm0gPSBUKSAlPiUgYXJyYW5nZShjb3VudHJ5X3JlZ2lvbl9jb2RlLCBkYXRlKQpjb2lfZG93bnNhbXBsZWQKYGBgCgoKCmBgYHtyfQppbnRlcmVzdGVkX2NvbHMgPC0gYygicmV0YWlsX2FuZF9yZWNyZWF0aW9uX3BlcmNlbnRfY2hhbmdlX2Zyb21fYmFzZWxpbmUiLAogICAgICAgICAgICAgICAgICAgICAiZ3JvY2VyeV9hbmRfcGhhcm1hY3lfcGVyY2VudF9jaGFuZ2VfZnJvbV9iYXNlbGluZSIsCiAgICAgICAgICAgICAgICAgICAgICJwYXJrc19wZXJjZW50X2NoYW5nZV9mcm9tX2Jhc2VsaW5lIiwKICAgICAgICAgICAgICAgICAgICAgInRyYW5zaXRfc3RhdGlvbnNfcGVyY2VudF9jaGFuZ2VfZnJvbV9iYXNlbGluZSIsCiAgICAgICAgICAgICAgICAgICAgICJ3b3JrcGxhY2VzX3BlcmNlbnRfY2hhbmdlX2Zyb21fYmFzZWxpbmUiLAogICAgICAgICAgICAgICAgICAgICAicmVzaWRlbnRpYWxfcGVyY2VudF9jaGFuZ2VfZnJvbV9iYXNlbGluZSIpCgpjb2xfbGFiZWxzIDwtIGMoIkF2ZXJhZ2UgUmV0YWlsIGFuZCBSZWNyZWF0aW9uIFBlcmNlbnQgQ2hhbmdlIGZyb20gQmFzZWxpbmUiLAogICAgICAgICAgICAgICAgICAgICAiQXZlcmFnZSBHcm9jZXJ5IGFuZCBQaGFybWFjeSBQZXJjZW50IENoYW5nZSBmcm9tIEJhc2VsaW5lIiwKICAgICAgICAgICAgICAgICAgICAgIkF2ZXJhZ2UgUGFya3MgUGVyY2VudCBDaGFuZ2UgZnJvbSBCYXNlbGluZSIsCiAgICAgICAgICAgICAgICAgICAgICJBdmVyYWdlIFRyYW5zaXQgU3RhdGlvbnMgUGVyY2VudCBDaGFuZ2UgZnJvbSBCYXNlbGluZSIsCiAgICAgICAgICAgICAgICAgICAgICJBdmVyYWdlIFdvcmtwbGFjZXMgUGVyY2VudCBDaGFuZ2UgZnJvbSBCYXNlbGluZSIsCiAgICAgICAgICAgICAgICAgICAgICJBdmVyYWdlIFJlc2lkZW50aWFsIFBlcmNlbnQgQ2hhbmdlIGZyb20gQmFzZWxpbmUiKQoKCmZvciAoaSBpbiAxOmxlbmd0aChjb2xfbGFiZWxzKSl7CiAgcHJpbnQoaSkKICBwbHQgPC0gZ2dwbG90KGNvaV9kb3duc2FtcGxlZCwKICAgICAgIGFlcyh4PWRhdGUsIHk9Z2V0KGludGVyZXN0ZWRfY29sc1tpXSksIGdyb3VwPWNvdW50cnlfcmVnaW9uX2NvZGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvcj1jb3VudHJ5X3JlZ2lvbl9jb2RlKSkrCiAgZ2VvbV9wb2ludChhZXMoeT1yb2xsbWVhbihnZXQoaW50ZXJlc3RlZF9jb2xzW2ldKSwgaz0xMCwgbmEucGFkPVRSVUUpKSwgc2l6ZT0uNSkrCiAgZ2VvbV9saW5lKGFlcyh5PXJvbGxtZWFuKGdldChpbnRlcmVzdGVkX2NvbHNbaV0pLCBrPTEwLCBuYS5wYWQ9VFJVRSkpKSsKICAjIGdlb21fcG9pbnQoc2l6ZT0uNSkrZ2VvbV9saW5lKCkrCiAgbGFicyh5ID0gY29sX2xhYmVsc1tpXSwgeCA9ICJEYXRlIiwgY29sb3IgPSAiQ291bnRyeSIpKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gIkhlbHZldGljYSIsIGZhY2UgPSAiYm9sZCIsIHNpemUgPSAoMTUpKSwKICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpKQogIHNhdmVfcGF0aCA8LSBwYXN0ZShjKCIuLy4uL2ltZ3MvIiwgaW50ZXJlc3RlZF9jb2xzW2ldLCAiLnBuZyIpLCBjb2xsYXBzZSA9ICIiKQogIGdnc2F2ZShzYXZlX3BhdGgpCiAgcHJpbnQocGx0KQp9CiMgZ2dwbG90KGNvaV9kb3duc2FtcGxlZCwKIyAgICAgICAgYWVzKHg9ZGF0ZSwgeT1ncm9jZXJ5X2FuZF9waGFybWFjeV9wZXJjZW50X2NoYW5nZV9mcm9tX2Jhc2VsaW5lLCBncm91cD1jb3VudHJ5X3JlZ2lvbl9jb2RlLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvcj1jb3VudHJ5X3JlZ2lvbl9jb2RlKSkrCiAgIyBnZW9tX3BvaW50KGFlcyh5PXJvbGxtZWFuKHJldGFpbF9hbmRfcmVjcmVhdGlvbl9wZXJjZW50X2NoYW5nZV9mcm9tX2Jhc2VsaW5lLCBrPTEwLCBuYS5wYWQ9VFJVRSkpLCBzaXplPS41KSsKIyAgIGdlb21fbGluZShhZXMoeT1yb2xsbWVhbihyZXRhaWxfYW5kX3JlY3JlYXRpb25fcGVyY2VudF9jaGFuZ2VfZnJvbV9iYXNlbGluZSwgaz0xMCwgbmEucGFkPVRSVUUpKSkrCiMgICAjIGdlb21fcG9pbnQoc2l6ZT0uNSkrZ2VvbV9saW5lKCkrCiMgICBsYWJzKHkgPSAiQXZlcmFnZSBHcm9jZXJ5IGFuZCBQaGFybWFjeSBQZXJjZW50IENoYW5nZSBmcm9tIEJhc2VsaW5lIiwgeCA9ICJEYXRlIiwgY29sb3IgPSAiQ291bnRyeSIpKwojICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAiSGVsdmV0aWNhIiwgZmFjZSA9ICJib2xkIiwgc2l6ZSA9ICgxNSkpLAojICAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSkKIyAgICMgZ2VvbV9saW5lKCkKYGBgCgpgYGB7cn0KdHhfY291bnR5X2RhdGEgPC0gdHhfZGF0YSAlPiUgZmlsdGVyKGNvdW50eV9uYW1lICE9ICJTdGF0ZXdpZGUgVW5hbGxvY2F0ZWQiKQp0eF90b3RhbF9zdGF0ZV9kYXRhIDwtIHR4X2RhdGEgJT4lIGZpbHRlcihjb3VudHlfbmFtZSA9PSAiU3RhdGV3aWRlIFVuYWxsb2NhdGVkIikKdHhfdG90YWxfc3RhdGVfZGF0YSRjdW11bGF0aXZlX2RlYXRocyA8LSBjdW1zdW0odHhfdG90YWxfc3RhdGVfZGF0YSRkZWF0aHMpCnR4X3RvdGFsX3N0YXRlX2RhdGEkY3VtdWxhdGl2ZV9jYXNlcyA8LSBjdW1zdW0odHhfdG90YWxfc3RhdGVfZGF0YSRjb25maXJtZWRfY2FzZXMpCnR4X2NvdW50eV9kYXRhCnR4X3RvdGFsX3N0YXRlX2RhdGEKYGBgCgpgYGB7cn0KCmBgYAoKClNpbmNlIHRoZSBhYm92ZSBkb2Vzbid0IHJlYWxseSBtYWtlIHNlbnNlIChvbmx5IDc4IGNvbmZpcm1lZCBjYXNlcyB3aXRoIG92ZXIgYSB0aG91c2FuZCBkZWF0aHMpLCBJIGFtIGdvaW5nIHRvIGFuYWx5emUgb24gYSBwZXIgY291bnR5IGJhc2lzIGFuZCBtYXliZSB0aGF0IGRhdGEgd2lsbCBiZSBtb3JlIGNsZWFyLgoKYGBge3J9CnR4X2J5X2RheV9iYXNlZF9vbl9jb3VudHkgPC0gdHhfY291bnR5X2RhdGEgJT4lIAogIHNlbGVjdChkYXRlLCBjb25maXJtZWRfY2FzZXMsIGRlYXRocykgJT4lCiAgZ3JvdXBfYnkoZGF0ZSkgJT4lIAogIHN1bW1hcmlzZV9hbGwoc3VtLCBuYS5ybSA9IFQpICU+JQogIGFycmFuZ2UoZGF0ZSkKCiMgaW50ZXJlc3RlZF9jb2xzIDwtIGMoImNvbmZpcm1lZF9jYXNlcyIsICJkZWF0aHMiKQojIGNvbF9sYWJlbHMgPC0gYygiVG90YWwgQ2FzZXMiLCAiVG90YWwgRGVhdGhzIikKIyAKIyBmb3IgKGkgaW4gMTpsZW5ndGgoY29sX2xhYmVscykpewojICAgcHJpbnQoaSkKIyAgIHRpdGxlIDwtIHBhc3RlKGMoIlRleGFzICIsIGNvbF9sYWJlbHNbaV0pLCBjb2xsYXBzZSA9ICIiKQojICAgcGx0IDwtIGdncGxvdCh0eF9ieV9kYXlfYmFzZWRfb25fY291bnR5LAojICAgICAgICBhZXMoeD1kYXRlLCB5PWdldChpbnRlcmVzdGVkX2NvbHNbaV0pKSkrCiMgICAjIGdlb21fcG9pbnQoYWVzKHk9cm9sbG1lYW4oZ2V0KGludGVyZXN0ZWRfY29sc1tpXSksIGs9MTAsIG5hLnBhZD1UUlVFKSksIHNpemU9LjUpKwojICAgIyBnZW9tX2xpbmUoYWVzKHk9cm9sbG1lYW4oZ2V0KGludGVyZXN0ZWRfY29sc1tpXSksIGs9MTAsIG5hLnBhZD1UUlVFKSkpKwojICAgIyBnZW9tX3BvaW50KHNpemU9LjUpK2dlb21fbGluZSgpKwojICAgICBnZW9tX2xpbmUoY29sb3IpKwojICAgbGFicyh5ID0gY29sX2xhYmVsc1tpXSwgeCA9ICJEYXRlIiwgdGl0bGUgPSB0aXRsZSkKIyAgICMgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAiSGVsdmV0aWNhIiwgZmFjZSA9ICJib2xkIiwgc2l6ZSA9ICgxNSkpLAojICAgIyAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpKQojICAgIyBzYXZlX3BhdGggPC0gcGFzdGUoYygiLi8uLi9pbWdzLyIsIGludGVyZXN0ZWRfY29sc1tpXSwgIi5wbmciKSwgY29sbGFwc2UgPSAiIikKIyAgICMgZ2dzYXZlKHNhdmVfcGF0aCkKIyAgIHByaW50KHBsdCkKIyB9CgpgYGAKYGBge3J9CnR4X2J5X2RheV9iYXNlZF9vbl9jb3VudHkKYGBgCgpgYGB7cn0KaW5zdGFsbC5wYWNrYWdlcygiZ2dyZXBlbCIpCmxpYnJhcnkoZ2dyZXBlbCkKYGBgCmBgYHtyfQp0eF9ieV9kYXlfYmFzZWRfb25fY291bnR5ICU+JSBwaXZvdF9sb25nZXIoIWRhdGUsIG5hbWVzX3RvID0gInR5cGUiLCB2YWx1ZXNfdG8gPSAiY291bnQiKQpgYGAKCgpgYGB7cn0KIyB0IDwtIHRpYmJsZSgiTWF4IiA9IGMoMzQzNzgsIDIyNDg5MjcpLCAiZGF0ZSIgPSBjKCIyMDIxLTAxLTI1IiwgIjIwMjEtMDEtMjUiKSwKIyAgICAgICAgICAgICAidHlwZSIgPSBjKCJkZWF0aHMiLCAiY29uZmlybWVkX2Nhc2VzIikpCiMgdCRkYXRlIDwtIGFzLkRhdGUodCRkYXRlKQojIHQgCgpkYXRhX2VuZHMgPC0gdHhfYnlfZGF5X2Jhc2VkX29uX2NvdW50eSAlPiUgcGl2b3RfbG9uZ2VyKCFkYXRlLCBuYW1lc190byA9ICJ0eXBlIiwgdmFsdWVzX3RvID0gImNvdW50IikgJT4lIAogIGdyb3VwX2J5KHR5cGUpICU+JSAKICB0b3BfbigxLCBjb3VudCkgCmRhdGFfZW5kcwoKYGBgCgoKCmBgYHtyfQpsaWJyYXJ5KHNjYWxlcykKIyBwbmcoIi4vLi4vaW1ncy90ZXhhc19jb3ZpZF9jYXNlc190b3RhbC5wbmciLCB3aWR0aCA9IDgwMCwgaGVpZ2h0ID0gODAwKQojIHR4X2J5X2RheV9iYXNlZF9vbl9jb3VudHkgJT4lIHBpdm90X2xvbmdlcighZGF0ZSwgbmFtZXNfdG8gPSAidHlwZSIsIHZhbHVlc190byA9ICJjb3VudCIpCmdncGxvdCh0eF9ieV9kYXlfYmFzZWRfb25fY291bnR5ICU+JSBwaXZvdF9sb25nZXIoIWRhdGUsIG5hbWVzX3RvID0gInR5cGUiLCB2YWx1ZXNfdG8gPSAiY291bnQiKSwKICAgICAgIGFlcyh4PWRhdGUsIHk9Y291bnQsIGdyb3VwPXR5cGUpKSsKICAgICAgICAgZ2VvbV9saW5lKGFlcyhjb2xvcj10eXBlKSkrCiAgIyBzY2FsZV95X2NvbnRpbnVvdXModHJhbnMgPSAibG9nMTAiLAogICMgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IHRyYW5zX2JyZWFrcygnbG9nMTAnLCBtYXRoX2Zvcm1hdCgxMF4ueCkpKSsKICBzY2FsZV9jb2xvcl9tYW51YWwobGFiZWxzID0gYygiQ29uZmlybWVkIENhc2VzIiwgIkRlYXRocyIpLCB2YWx1ZXMgPSBjKCJjb25maXJtZWRfY2FzZXMiPSJibHVlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJkZWF0aHMiPSJyZWQiKSkrCiAgbGFicyh5ID0gIlRvdGFsIFBlcnNvbnMiLCB4ID0gIkRhdGUiLCBjb2xvciA9ICIiKSsKICBnZW9tX3RleHRfcmVwZWwoYWVzKGxhYmVsID0gY291bnQpLCBkYXRhID0gZGF0YV9lbmRzLCBzaXplPTMpKwogICMgc2NhbGVfeV9jb250aW51b3VzKHNlYy5heGlzID0gc2VjX2F4aXMofiAuLCBicmVha3MgPSBkYXRhX2VuZHMpKSsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJIZWx2ZXRpY2EiLCBmYWNlID0gImJvbGQiLCBzaXplID0gKDE1KSkpKwogIGdndGl0bGUoIlRleGFzIENPVklELTE5IENhc2VzIikKICAKIyBwbHQrIAojIGdncGxvdCh0LCAKIyAgICAgICAgICAgICAgYWVzKHg9RGF0ZSwgeT0gTWF4KSkrCiMgICBnZW9tX3BvaW50KCkKIyBwbHQgKyBnZW9tX3RleHRfcmVwZWwoYWVzKGxhYmVsID0gTWF4KSwgZGF0YSA9IHQsIGZvbnRmYWNlPSJwbGFpbiIsIGNvbG9yPSJibGFjayIsCiMgICAgICAgICAgICAgICAgICAgc2l6ZT0zKQojIGRldi5vZmYoKQoKZ2dzYXZlKCIuLy4uL2ltZ3MvdGV4YXNfY292aWRfY2FzZXNfdG90YWwucG5nIikKICAjIHNjYWxlX3lfbG9nMTAoKQogICAgICAgICAjIGxhYnMoeSA9ICJUb3RhbCBQZXJzb25zIiwgeCA9ICJEYXRlIikpCgojICkKIyAKIyBwbHQgPC0gZ2dwbG90KGNvaV9kb3duc2FtcGxlZCwKIyAgICAgICAgYWVzKHg9ZGF0ZSwgeT1nZXQoaW50ZXJlc3RlZF9jb2xzW2ldKSwgZ3JvdXA9Y291bnRyeV9yZWdpb25fY29kZSwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3I9Y291bnRyeV9yZWdpb25fY29kZSkpKwojICAgZ2VvbV9wb2ludChhZXMoeT1yb2xsbWVhbihnZXQoaW50ZXJlc3RlZF9jb2xzW2ldKSwgaz0xMCwgbmEucGFkPVRSVUUpKSwgc2l6ZT0uNSkrCiMgICBnZW9tX2xpbmUoYWVzKHk9cm9sbG1lYW4oZ2V0KGludGVyZXN0ZWRfY29sc1tpXSksIGs9MTAsIG5hLnBhZD1UUlVFKSkpKwojICAgIyBnZW9tX3BvaW50KHNpemU9LjUpK2dlb21fbGluZSgpKwojICAgbGFicyh5ID0gY29sX2xhYmVsc1tpXSwgeCA9ICJEYXRlIiwgY29sb3IgPSAiQ291bnRyeSIpKwojICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAiSGVsdmV0aWNhIiwgZmFjZSA9ICJib2xkIiwgc2l6ZSA9ICgxNSkpLAojICAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSkKIyAgIHNhdmVfcGF0aCA8LSBwYXN0ZShjKCIuLy4uL2ltZ3MvIiwgaW50ZXJlc3RlZF9jb2xzW2ldLCAiLnBuZyIpLCBjb2xsYXBzZSA9ICIiKQojICAgZ2dzYXZlKHNhdmVfcGF0aCkKIyAgIHByaW50KHBsdCkKYGBgCgpgYGB7cn0KdHhfY291bnR5X2RhdGEKYGBgCgoKYGBge3J9CnN1YnNldF9jZW5zdXMKCnR4X3N0YXRlIDwtIG1hcF9kYXRhKCJzdGF0ZSIpICU+JSBzdWJzZXQocmVnaW9uID09ICJ0ZXhhcyIpCnR4X2NvdW50eV9tYXBfZGF0YSA8LSBtYXBfZGF0YSgiY291bnR5IikgJT4lIHN1YnNldChyZWdpb24gPT0gInRleGFzIikKCnR4X3N0YXRlCnR4X2NvdW50eV9tYXBfZGF0YQoKZ2NvdW50eSA8LSBtYXBfZGF0YSgiY291bnR5IikKIyAKIyBmaXBzdGFiIDwtCiMgICAgICAgdHJhbnNtdXRlKG1hcHM6OmNvdW50eS5maXBzLCBmaXBzLCBjb3VudHkgPSBzdWIoIjouKiIsICIiLCBwb2x5bmFtZSkpICU+JQojICAgICAgIHVuaXF1ZSgpICU+JQojICAgICAgIHNlcGFyYXRlKGNvdW50eSwgYygicmVnaW9uIiwgInN1YnJlZ2lvbiIpLCBzZXAgPSAiLCIpCgojIEZvcm1hdCB3aXRoIHN1YnJlZ2lvbnMKZmlwc3RhYiA8LQogIHRyYW5zbXV0ZShtYXBzOjpjb3VudHkuZmlwcywgZmlwcywgY291bnR5ID0gc3ViKCI6LioiLCAiIiwgcG9seW5hbWUpKSAlPiUKICB1bmlxdWUoKSAlPiUKICBzZXBhcmF0ZShjb3VudHksIGMoInJlZ2lvbiIsICJzdWJyZWdpb24iKSwgc2VwID0gIiwiKQogIAogICMgIyBDb21iaW5lIGluIGRlc2lyZWQgb3JkZXIgKE5BIGZvciBtaXNzaW5nKQogICMgZ2NvdW50eSA8LSBsZWZ0X2pvaW4oZ2NvdW50eSwgZmlwc3RhYiwgYygicmVnaW9uIiwgInN1YnJlZ2lvbiIpKQoKCnR4X2dlb19kYXRhIDwtIGxlZnRfam9pbihnY291bnR5LCBmaXBzdGFiLCBjKCJyZWdpb24iLCAic3VicmVnaW9uIikpICU+JQogIGxlZnRfam9pbihzdWJzZXRfY2Vuc3VzLCBjKCJmaXBzIiA9ICJjb3VudHlfZmlwc19jb2RlIikpICU+JSBmaWx0ZXIocmVnaW9uID09ICJ0ZXhhcyIpICU+JQogIHVuaXF1ZSgpCgp0eF9nZW9fZGF0YSRkaW5mZWN0X3BjbHMgPC0gY3V0KDEwMCAqIHBlcmNlbnRfcmFuayh0eF9nZW9fZGF0YSRwY3RfaW5mZWN0ZWQpLCBzZXEoMCwgMTAwLCBsZW4gPSAxMSksCiAgICAgICAgICAgICAgICAgICAgICAgIGluY2x1ZGUubG93ZXN0ID0gVFJVRSkKdHhfZ2VvX2RhdGEkZGVhdGhzX3BjbHMgPC0gY3V0KDEwMCAqIHBlcmNlbnRfcmFuayh0eF9nZW9fZGF0YSRwY3RfZGVhdGhzKSwgc2VxKDAsIDEwMCwgbGVuID0gMTEpLAogICAgICAgICAgICAgICAgICAgICAgICBpbmNsdWRlLmxvd2VzdCA9IFRSVUUpCnR4X2dlb19kYXRhJGRlYXRoX3JhdGVfcGNscyA8LSBjdXQoMTAwICogcGVyY2VudF9yYW5rKHR4X2dlb19kYXRhJGRlYXRoX3JhdGUpLCBzZXEoMCwgMTAwLCBsZW4gPSAxMSksCiAgICAgICAgICAgICAgICAgICAgICAgIGluY2x1ZGUubG93ZXN0ID0gVFJVRSkKCnR4X2dlb19kYXRhCgoKIyAKIyAjIExvd2VyY2FzZQojIHR4X2NvdW50eV9kYXRhJGNvdW50eV9uYW1lIDwtIHRvbG93ZXIodHhfY291bnR5X2RhdGEkY291bnR5X25hbWUpCiMgCiMgIyBSZW1vdmUgJyBjb3VudHknCiMgdHhfY291bnR5X2RhdGEkY291bnR5X25hbWUgPC0gc3ViKCJcXHMqY291bnR5XFxiLioiLCAiIiwgdHhfY291bnR5X2RhdGEkY291bnR5X25hbWUpCiMgdHhfY291bnR5X2RhdGEKIyAKIyAjIEdldCBtYXggY29uZmlybWVkIGNhc2VzIGFuZCBkZWF0aHMKIyB0eF9jb3VudHlfZGF0YQojIAojIAojICMgIyBKb2luIHRoZSBkYXRhIHdpdGggc3RhdGUgZ2VvIGluZm8KIyAjIHR4X2dlb19kYXRhIDwtIGxlZnRfam9pbih0eF9jb3VudHlfbWFwX2RhdGEsIHR4X2NvdW50eV9kYXRhLCBieSA9IGMoInN1YnJlZ2lvbiIgPSAiY291bnR5X25hbWUiKSkKIyAjIHR4X2dlb19kYXRhCmBgYApgYGB7cn0KCm15Y29sb3JzIDwtIGNvbG9yUmFtcFBhbGV0dGUoYnJld2VyLnBhbCg5LCAiUmVkcyIpKSgxMSkKCmdncGxvdCh0eF9nZW9fZGF0YSkrCiAgY29vcmRfbWFwKCkgKyBnZ3RoZW1lczo6dGhlbWVfbWFwKCkrCiAgZ2VvbV9wb2x5Z29uKGFlcyhsb25nLCBsYXQsIGdyb3VwID0gZ3JvdXAsIGZpbGw9ZGVhdGhfcmF0ZV9wY2xzKSkrCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gbXljb2xvcnMsIG5hLnZhbHVlID0gImdyZXkiKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAiSGVsdmV0aWNhIiwgZmFjZSA9ICJib2xkIiwgc2l6ZSA9ICgxNSkpLCBsZWdlbmQucG9zaXRpb24gPSAibGVmdCIpKwogICMgICAgICAgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9IE5BKSwKICAgICAgICAjIGxlZ2VuZC5wb3NpdGlvbiA9ICJsZWZ0IikrCiAgbGFicyhmaWxsPSJQZXJjZW50aWxlIikgKyBnZ3RpdGxlKCJUZXhhcyBDb3VudHkgTW9ydGFsaXR5IFJhdGUgUGVyY2VudGlsZXMiKQoKZ2dzYXZlKCIuLy4uL2ltZ3MvdGV4YXNfY291bnR5X21vcnRhbGl0eV9wZXJjZW50aWxlcy5wbmciKQoKIyBnZ3Bsb3QodHhfZ2VvX2RhdGEpICsKIyAgICAgICBnZW9tX3BvbHlnb24oYWVzKGxvbmcsIGxhdCwgZ3JvdXAgPSBncm91cCwgZmlsbCA9IGRlYXRoX3JhdGVfcGNscyksCiMgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gImdyZXkiLCBzaXplID0gMC4xKSArCiMgICAgICAgIyBnZW9tX3BvbHlnb24oYWVzKGxvbmcsIGxhdCwgZ3JvdXAgPSBncm91cCksCiMgICAgICAgIyAgICAgICAgICAgICAgZmlsbCA9IE5BLCBkYXRhID0gZ3VzYSwgY29sb3IgPSAibGlnaHRncmV5IikgKwojICAgICAgIGNvb3JkX21hcCgiYm9ubmUiLCBwYXJhbWV0ZXJzID0gNDEuNikgKyBnZ3RoZW1lczo6dGhlbWVfbWFwKCkgKwojICAgICAgIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IG15Y29sb3JzLCBuYS52YWx1ZSA9ICJncmV5IikgKwojICAgICAgICMgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJ2aXJpZGlzIiwgbmEudmFsdWUgPSAiZ3JleSIpICsKIyAgICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJIZWx2ZXRpY2EiLCBmYWNlID0gImJvbGQiLCBzaXplID0gKDE1KSksCiMgICAgICAgICAgICAgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9IE5BKSwKIyAgICAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibGVmdCIpCgoKCiMgaWYgKHBlcmNlbnRpbGUgPT0gVFJVRSl7CiMgICAgIHBsdCA8LSBnZ3Bsb3QoZ2NvdW50eV9wb3ApICsKIyAgICAgICBnZW9tX3BvbHlnb24oYWVzKGxvbmcsIGxhdCwgZ3JvdXAgPSBncm91cCwgZmlsbCA9IHBjbHMpLAojICAgICAgICAgICAgICAgICAgICBjb2xvciA9ICJncmV5Iiwgc2l6ZSA9IDAuMSkgKwojICAgICAgIGdlb21fcG9seWdvbihhZXMobG9uZywgbGF0LCBncm91cCA9IGdyb3VwKSwKIyAgICAgICAgICAgICAgICAgICAgZmlsbCA9IE5BLCBkYXRhID0gZ3VzYSwgY29sb3IgPSAibGlnaHRncmV5IikgKwojICAgICAgIGNvb3JkX21hcCgiYm9ubmUiLCBwYXJhbWV0ZXJzID0gNDEuNikgKyBnZ3RoZW1lczo6dGhlbWVfbWFwKCkgKwojICAgICAgIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IG15Y29sb3JzLCBuYS52YWx1ZSA9ICJncmV5IikgKwojICAgICAgICMgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJ2aXJpZGlzIiwgbmEudmFsdWUgPSAiZ3JleSIpICsKIyAgICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJIZWx2ZXRpY2EiLCBmYWNlID0gImJvbGQiLCBzaXplID0gKDE1KSksCiMgICAgICAgICAgICAgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9IE5BKSwgCiMgICAgICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImxlZnQiKQogICAgCgojIHBsdCA8LSBnZ3Bsb3QoZ2NvdW50eV9wb3ApICsKIyAgICAgICBnZW9tX3BvbHlnb24oYWVzKGxvbmcsIGxhdCwgZ3JvdXAgPSBncm91cCwgZmlsbCA9IGRpbmZlY3RfcGNscyksCiMgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gImdyZXkiLCBzaXplID0gMC4xKSArCiMgICAgICAgZ2VvbV9wb2x5Z29uKGFlcyhsb25nLCBsYXQsIGdyb3VwID0gZ3JvdXApLAojICAgICAgICAgICAgICAgICAgICBmaWxsID0gTkEsIGRhdGEgPSBndXNhLCBjb2xvciA9ICJsaWdodGdyZXkiKSArCiMgICAgICAgY29vcmRfbWFwKCJib25uZSIsIHBhcmFtZXRlcnMgPSA0MS42KSArIGdndGhlbWVzOjp0aGVtZV9tYXAoKSArCiMgICAgICAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gbXljb2xvcnMsIG5hLnZhbHVlID0gImdyZXkiKSArCiMgICAgICAgIyBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gInZpcmlkaXMiLCBuYS52YWx1ZSA9ICJncmV5IikgKwojICAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gIkhlbHZldGljYSIsIGZhY2UgPSAiYm9sZCIsIHNpemUgPSAoMTUpKSwKIyAgICAgICAgICAgICBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gTkEpLAojICAgICAgICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJsZWZ0IikKCiMgZ2dwbG90KHR4X2dlb19kYXRhKSArCiMgICAgICAgICAgY29vcmRfbWFwKCkgKyAKIyAgIGdndGhlbWVzOjp0aGVtZV9tYXAoKSsKIyAgIGdlb21fcG9seWdvbihhZXMobG9uZywgbGF0LCBncm91cCA9IHN1YnJlZ2lvbiwgZmlsbCA9IGNvbmZpcm1lZF9jYXNlcykpCiMgcGNfY29udF9pb3dhIDwtIGdlb21fcG9seWdvbihhZXMobG9uZywgbGF0LCBncm91cCA9IGdyb3VwLCBmaWxsID0gcGNoYW5nZSksCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvciA9ICJncmV5Iiwgc2l6ZSA9IDAuMikKYGBgCmBgYHtyfQpkYXRhX2VuZHMgPC0gZGFsbGFzX2RhdGEgJT4lIHBpdm90X2xvbmdlcighZGF0ZSwgbmFtZXNfdG8gPSAidHlwZSIsIHZhbHVlc190byA9ICJjb3VudCIpICU+JSAKICBncm91cF9ieSh0eXBlKSAlPiUgCiAgdG9wX24oMSwgY291bnQpIApkYXRhX2VuZHMKYGBgCgpgYGB7cn0KIyBkYWxsYXNfZGF0YSA8LSB0eF9jb3VudHlfZGF0YSAlPiUgZmlsdGVyKGNvdW50eV9uYW1lID09ICJkYWxsYXMiKSAKZGFsbGFzX2RhdGEgPC0gdHhfY291bnR5X2RhdGEgJT4lIGZpbHRlcihjb3VudHlfbmFtZSA9PSAiRGFsbGFzIENvdW50eSIpICU+JSAKICBzZWxlY3QoZGF0ZSwgY29uZmlybWVkX2Nhc2VzLCBkZWF0aHMpCgpkYXRhX2VuZHMgPC0gZGFsbGFzX2RhdGEgJT4lIHBpdm90X2xvbmdlcighZGF0ZSwgbmFtZXNfdG8gPSAidHlwZSIsIHZhbHVlc190byA9ICJjb3VudCIpICU+JSAKICBncm91cF9ieSh0eXBlKSAlPiUgCiAgdG9wX24oMSwgY291bnQpIAoKZ2dwbG90KGRhbGxhc19kYXRhICU+JSBwaXZvdF9sb25nZXIoIWRhdGUsIG5hbWVzX3RvID0gInR5cGUiLCB2YWx1ZXNfdG8gPSAiY291bnQiKSwKICAgICAgIGFlcyh4PWRhdGUsIHk9Y291bnQsIGdyb3VwPXR5cGUpKSsKICAgICAgICAgZ2VvbV9saW5lKGFlcyhjb2xvcj10eXBlKSkrCiAgIyBzY2FsZV95X2NvbnRpbnVvdXModHJhbnMgPSAibG9nMTAiLCBsYWJlbHMgPSB0cmFuc19icmVha3MoImxvZzEwIiwgbWF0aF9mb3JtYXQoMTBeLngpKSkrCiAgIyBzY2FsZV95X2xvZzEwKGJyZWFrcz1jKDEwMCwgMzAwLCA1MDAsIDEwMDAsIDMwMDAsIDUwMDAsIDEwMDAwLCAzMDAwMCwgNTAwMDAsIDEwMDAwMCwgMzAwMDAwKSwKICAjICAgICAgICAgICAgICAgbGFiZWxzPWMoJzEwMCcsICczMDAnLCAnNTAwJywgJzEwMDAnLCAnMzAwMCcsICc1MDAwJywgJzEwMDAwJywgJzMwMDAwJywgJzUwMDAwJywgJzEwMDAwMCcsICczMDAwMDAnKSkrCiAgc2NhbGVfY29sb3JfbWFudWFsKGxhYmVscyA9IGMoIkNvbmZpcm1lZCBDYXNlcyIsICJEZWF0aHMiKSwgdmFsdWVzID0gYygiY29uZmlybWVkX2Nhc2VzIj0iYmx1ZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZGVhdGhzIj0icmVkIikpKwogIGxhYnMoeSA9ICJUb3RhbCBQZXJzb25zIiwgeCA9ICJEYXRlIiwgY29sb3IgPSAiIikrCiAgZ2VvbV90ZXh0X3JlcGVsKGFlcyhsYWJlbCA9IGNvdW50KSwgZGF0YSA9IGRhdGFfZW5kcywgc2l6ZT0zKSsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJIZWx2ZXRpY2EiLCBmYWNlID0gImJvbGQiLCBzaXplID0gKDE1KSkpKwogIGdndGl0bGUoIkRhbGxhcyBDT1ZJRC0xOSBDYXNlcyIpCiAgZ2dzYXZlKCIuLy4uL2ltZ3MvZGFsbGFzX2NvdmlkX2Nhc2VzX3RvdGFsLnBuZyIpCmBgYAoKCmBgYHtyfQpzZ2NvdW50eSA8LSBtYXBfZGF0YSgic3RhdGUiKQoKIyBGb3JtYXQgd2l0aCBzdWJyZWdpb25zCmZpcHN0YWIgPC0KICB0cmFuc211dGUobWFwczo6Y291bnR5LmZpcHMsIGZpcHMsIGNvdW50eSA9IHN1YigiOi4qIiwgIiIsIHBvbHluYW1lKSkgJT4lCiAgdW5pcXVlKCkgJT4lCiAgc2VwYXJhdGUoY291bnR5LCBjKCJyZWdpb24iLCAic3VicmVnaW9uIiksIHNlcCA9ICIsIikKCnVzX2dlb19kYXRhIDwtIGxlZnRfam9pbihnY291bnR5LCBmaXBzdGFiLCBjKCJyZWdpb24iLCAic3VicmVnaW9uIikpICU+JQogIGxlZnRfam9pbihzdWJzZXRfY2Vuc3VzLCBjKCJmaXBzIiA9ICJjb3VudHlfZmlwc19jb2RlIikpICU+JQogIHVuaXF1ZSgpICU+JSBzZWxlY3QobG9uZywgbGF0LCByZWdpb24sIHN1YnJlZ2lvbiwgZ3JvdXAsIGNvbmZpcm1lZF9jYXNlcywgZGVhdGhzLCBtZWRpYW5faW5jb21lLCAKICAgICAgICAgICAgICAgICAgICAgIG1hbGVfcG9wLCBmZW1hbGVfcG9wLCB0b3RhbF9wb3AsIG1lZGlhbl9hZ2UsCiAgICAgICAgICAgICAgICAgICAgICB3b3JrZWRfYXRfaG9tZSkKIyB1c19nZW9fZGF0YQoKIyBHZXQgdGhlIHRvdGFsIGNhc2VzIGJ5IHN0YXRlCnN0YXRlX2RhdGFfYnJlYWtkb3duIDwtIHVzX2dlb19kYXRhICU+JSAKICBkcm9wX25hKCkgJT4lIHNlbGVjdChyZWdpb24sIHN1YnJlZ2lvbiwgY29uZmlybWVkX2Nhc2VzLCBkZWF0aHMsIG1lZGlhbl9pbmNvbWUsIAogICAgICAgICAgICAgICAgICAgICAgbWFsZV9wb3AsIGZlbWFsZV9wb3AsIHRvdGFsX3BvcCwgbWVkaWFuX2FnZSwKICAgICAgICAgICAgICAgICAgICAgIHdvcmtlZF9hdF9ob21lKSAlPiUgdW5pcXVlKCkgJT4lCiAgZ3JvdXBfYnkocmVnaW9uKSAlPiUgc2VsZWN0X2lmKGlzLm51bWVyaWMpICU+JQogIHN1bW1hcmlzZV9hbGwoc3VtKQoKc3RhdGVfZGF0YV9icmVha2Rvd24kcGN0X2RlYXRocyA8LSBzdGF0ZV9kYXRhX2JyZWFrZG93biRkZWF0aHMvc3RhdGVfZGF0YV9icmVha2Rvd24kdG90YWxfcG9wCnN0YXRlX2RhdGFfYnJlYWtkb3duJHBjdF9pbmZlY3QgPC0gc3RhdGVfZGF0YV9icmVha2Rvd24kY29uZmlybWVkX2Nhc2VzL3N0YXRlX2RhdGFfYnJlYWtkb3duJHRvdGFsX3BvcApzdGF0ZV9kYXRhX2JyZWFrZG93biRkZWF0aF9yYXRlIDwtIHN0YXRlX2RhdGFfYnJlYWtkb3duJGRlYXRocy9zdGF0ZV9kYXRhX2JyZWFrZG93biRjb25maXJtZWRfY2FzZXMKCnByaW50KHN0YXRlX2RhdGFfYnJlYWtkb3duICU+JSBhcnJhbmdlKGRlYXRoX3JhdGUsIGRlY3JlYXNpbmc9VCkpCgpzdGF0ZV9nZW9fZGF0YSA8LSB1c19nZW9fZGF0YSAlPiUgc2VsZWN0KGxvbmcsIGxhdCwgcmVnaW9uLCBncm91cCkgJT4lIGxlZnRfam9pbihzdGF0ZV9kYXRhX2JyZWFrZG93biwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieSA9ICJyZWdpb24iKQoKc3RhdGVfZ2VvX2RhdGEKCiMgZ2dwbG90KHR4X2J5X2RheV9iYXNlZF9vbl9jb3VudHkgJT4lIHBpdm90X2xvbmdlcighZGF0ZSwgbmFtZXNfdG8gPSAidHlwZSIsIHZhbHVlc190byA9ICJjb3VudCIpLAojICAgICAgICBhZXMoeD1kYXRlLCB5PWNvdW50LCBncm91cD10eXBlLCBjb2xvciA9IHR5cGUpKSsKIyAgICAgICAgICBnZW9tX2xpbmUoKSsKIyAgIHNjYWxlX3lfY29udGludW91cyh0cmFucyA9ICJsb2cxMCIsCiMgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gdHJhbnNfYnJlYWtzKCdsb2cxMCcsIG1hdGhfZm9ybWF0KDEwXi54KSkpKwojICAgc2NhbGVfY29sb3JfbWFudWFsKGxhYmVscyA9IGMoIkNvbmZpcm1lZCBDYXNlcyIsICJEZWF0aHMiKSwgdmFsdWVzID0gYygiY29uZmlybWVkX2Nhc2VzIj0iYmx1ZSIsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJkZWF0aHMiPSJyZWQiKSkrCiMgICBsYWJzKHkgPSAiVG90YWwgUGVyc29ucyIsIHggPSAiRGF0ZSIsIGNvbG9yID0gIiIpKwojICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAiSGVsdmV0aWNhIiwgZmFjZSA9ICJib2xkIiwgc2l6ZSA9ICgxNSkpKSsKIyAgIGdndGl0bGUoIlVTIENPVklELTE5IENhc2VzIikKICAjIGdnc2F2ZSgiLi8uLi9pbWdzL3RleGFzX2NvdmlkX2Nhc2VzX3RvdGFsLnBuZyIpCmBgYAoKYGBge3J9CiMgc3RhdGVfZ2VvX2RhdGEkc3RhdGVfZ3JvdXAgPC0gZmFjdG9yCnN0YXRlX2dlb19kYXRhJHN0YXRlX2dyb3VwIDwtIGZhY3RvcihzdGF0ZV9nZW9fZGF0YSRyZWdpb24pIApzdGF0ZV9nZW9fZGF0YSRzdGF0ZV9ncm91cCA8LSBhcy5udW1lcmljKHN0YXRlX2dlb19kYXRhJHN0YXRlX2dyb3VwKQpzdGF0ZV9nZW9fZGF0YQpgYGAKCgoKYGBge3J9CnN0YXRlX2RhdGFfYnJlYWtkb3duCmBgYApgYGB7cn0KIyBodHRwOi8vaG9tZXBhZ2Uuc3RhdC51aW93YS5lZHUvfmx1a2UvY2xhc3Nlcy9TVEFUNDU4MC0yMDIwL21hcHMuaHRtbAoKbGlicmFyeShzY2FsZXMpCnNwIDwtIHNlbGVjdChzdGF0ZV9kYXRhX2JyZWFrZG93biwgcmVnaW9uID0gcmVnaW9uLCBkZWF0aF9yYXRlKQpndXNhIDwtIG1hcF9kYXRhKCJzdGF0ZSIpCgpndXNhX3BvcCA8LSBsZWZ0X2pvaW4oZ3VzYSwgc3AsICJyZWdpb24iKQpndXNhX3BvcAoKZ2dwbG90KGd1c2FfcG9wKSArCiAgICBnZW9tX3BvbHlnb24oYWVzKGxvbmcsIGxhdCwgZ3JvdXAgPSBncm91cCwgZmlsbCA9IGRlYXRoX3JhdGUpLCBjb2xvcj0iZ3JleSIpICsKICAgIGNvb3JkX21hcCgiYm9ubmUiLCBwYXJhbWV0ZXJzID0gNDEuNikgKwogICAgZ2d0aGVtZXM6OnRoZW1lX21hcCgpKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gIkhlbHZldGljYSIsIGZhY2UgPSAiYm9sZCIsIHNpemUgPSAoMTUpKSkrCiAgc2NhbGVfZmlsbF9ncmFkaWVudChsYWJlbHMgPSBwZXJjZW50KSsKICBnZ3RpdGxlKCJNb3J0YWxpdHkgUmF0ZSBieSBTdGF0ZSIpKwogIGxhYnMoZmlsbD0iTW9ydGFsaXR5IFJhdGUiKQoKZ2dzYXZlKCIuLy4uL2ltZ3MvbW9ydGFsaXR5X3JhdGVfYnlfc3RhdGUucG5nIikKYGBgCmBgYHtyfQp0eF9kYXRhCmNhc2VzX3BsdXNfY2Vuc3VzCmBgYAoKCgpgYGB7cn0KdHhfY291bnR5X2RhdGEKYGBgCmBgYHtyfQojIEdldCB0aGUgZmlyc3Qgb2NjdXJyZW5jZXMgb2YgY292aWQgY2FzZSBhZnRlciBmaXJzdCB0eCBjYXNlCnR4X2ZpcnN0X2Nhc2VzX2J5X2NvdW50eSA8LSB0eF9jb3VudHlfZGF0YSAlPiUgZmlsdGVyKGNvbmZpcm1lZF9jYXNlcyA+IDApICU+JSAKICBncm91cF9ieShjb3VudHlfbmFtZSkgJT4lCiAgYXJyYW5nZShkYXRlKSAlPiUgc2xpY2VfbWluKG9yZGVyX2J5ID0gZGF0ZSwgbiA9IDEpICU+JSAKICBzZWxlY3QoY291bnR5X2ZpcHNfY29kZSwgY291bnR5X25hbWUsIGRhdGUpCgpmaXJzdF9kYXlfaW5fdHggPC0gbWluKHR4X2ZpcnN0X2Nhc2VzX2J5X2NvdW50eSRkYXRlKQoKdHhfZmlyc3RfY2FzZXNfYnlfY291bnR5IDwtIHR4X2ZpcnN0X2Nhc2VzX2J5X2NvdW50eSAlPiUgCiAgbXV0YXRlKGRheXNfZnJvbV9maXJzdF90eF9jYXNlID0gZGF0ZSAtIGZpcnN0X2RheV9pbl90eCkgJT4lCiAgbXV0YXRlKGNvdW50eV9maXBzX2NvZGUgPSBhcy5pbnRlZ2VyKGNvdW50eV9maXBzX2NvZGUpKQoKdHhfZmlyc3RfY2FzZXNfYnlfY291bnR5CmBgYAoKYGBge3J9CnR4X2ZpcnN0X2Nhc2VzX2J5X2NvdW50eSAlPiUgZmlsdGVyKGRheXNfZnJvbV9maXJzdF90eF9jYXNlID09IHRpbWVfbGVuZ3RoKDAsICJkYXlzIikpCmBgYAoKCmBgYHtyfQp0eF9zdGF0ZSA8LSBtYXBfZGF0YSgic3RhdGUiKSAlPiUgc3Vic2V0KHJlZ2lvbiA9PSAidGV4YXMiKQp0eF9jb3VudHlfbWFwX2RhdGEgPC0gbWFwX2RhdGEoImNvdW50eSIpICU+JSBzdWJzZXQocmVnaW9uID09ICJ0ZXhhcyIpCgpnY291bnR5IDwtIG1hcF9kYXRhKCJjb3VudHkiKQoKIyBGb3JtYXQgd2l0aCBzdWJyZWdpb25zCmZpcHN0YWIgPC0KICB0cmFuc211dGUobWFwczo6Y291bnR5LmZpcHMsIGZpcHMsIGNvdW50eSA9IHN1YigiOi4qIiwgIiIsIHBvbHluYW1lKSkgJT4lCiAgdW5pcXVlKCkgJT4lCiAgc2VwYXJhdGUoY291bnR5LCBjKCJyZWdpb24iLCAic3VicmVnaW9uIiksIHNlcCA9ICIsIikgJT4lIGZpbHRlcihyZWdpb24gPT0gInRleGFzIikKCgpmaXBzdGFiCnR4X2dlb19kYXlzIDwtIGxlZnRfam9pbihnY291bnR5LCBmaXBzdGFiLCBjKCJyZWdpb24iLCAic3VicmVnaW9uIikpICU+JQogIGxlZnRfam9pbih0eF9maXJzdF9jYXNlc19ieV9jb3VudHksIGMoImZpcHMiID0gImNvdW50eV9maXBzX2NvZGUiKSkgJT4lIGZpbHRlcihyZWdpb24gPT0gInRleGFzIikgJT4lCiAgdW5pcXVlKCkKCnR4X2dlb19kYXlzCiMgCiMgdHhfZ2VvX2RhdGEkZGluZmVjdF9wY2xzIDwtIGN1dCgxMDAgKiBwZXJjZW50X3JhbmsodHhfZ2VvX2RhdGEkcGN0X2luZmVjdGVkKSwgc2VxKDAsIDEwMCwgbGVuID0gMTEpLAojICAgICAgICAgICAgICAgICAgICAgICAgIGluY2x1ZGUubG93ZXN0ID0gVFJVRSkKIyB0eF9nZW9fZGF0YSRkZWF0aHNfcGNscyA8LSBjdXQoMTAwICogcGVyY2VudF9yYW5rKHR4X2dlb19kYXRhJHBjdF9kZWF0aHMpLCBzZXEoMCwgMTAwLCBsZW4gPSAxMSksCiMgICAgICAgICAgICAgICAgICAgICAgICAgaW5jbHVkZS5sb3dlc3QgPSBUUlVFKQojIHR4X2dlb19kYXRhJGRlYXRoX3JhdGVfcGNscyA8LSBjdXQoMTAwICogcGVyY2VudF9yYW5rKHR4X2dlb19kYXRhJGRlYXRoX3JhdGUpLCBzZXEoMCwgMTAwLCBsZW4gPSAxMSksCiMgICAgICAgICAgICAgICAgICAgICAgICAgaW5jbHVkZS5sb3dlc3QgPSBUUlVFKQojIAojIHR4X2dlb19kYXRhCgojICMgTG93ZXJjYXNlCiMgdHhfY291bnR5X2RhdGEkY291bnR5X25hbWUgPC0gdG9sb3dlcih0eF9jb3VudHlfZGF0YSRjb3VudHlfbmFtZSkKIyAKIyAjIFJlbW92ZSAnIGNvdW50eScKIyB0eF9jb3VudHlfZGF0YSRjb3VudHlfbmFtZSA8LSBzdWIoIlxccypjb3VudHlcXGIuKiIsICIiLCB0eF9jb3VudHlfZGF0YSRjb3VudHlfbmFtZSkKIyB0eF9jb3VudHlfZGF0YQpgYGAKCmBgYHtyfQpnZ3Bsb3QodHhfZ2VvX2RheXMgJT4lIG11dGF0ZShkYXlzX2Zyb21fZmlyc3RfdHhfY2FzZSA9IGFzLmludGVnZXIoZGF5c19mcm9tX2ZpcnN0X3R4X2Nhc2UpKSkgKwogIGNvb3JkX21hcCgpICsgZ2d0aGVtZXM6OnRoZW1lX21hcCgpKwogIGdlb21fcG9seWdvbihhZXMobG9uZywgbGF0LCBncm91cCA9IGdyb3VwLCBmaWxsPWRheXNfZnJvbV9maXJzdF90eF9jYXNlKSkrCiAgIyBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBteWNvbG9ycywgbmEudmFsdWUgPSAiZ3JleSIpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJIZWx2ZXRpY2EiLCBmYWNlID0gImJvbGQiLCBzaXplID0gKDE1KSksIGxlZ2VuZC5wb3NpdGlvbiA9ICJsZWZ0IikrCiAgIyAgICAgICBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gTkEpLAogICAgICAgICMgbGVnZW5kLnBvc2l0aW9uID0gImxlZnQiKSsKICBsYWJzKGZpbGw9IkRheXMgZnJvbSBGaXJzdCBUWCBDYXNlIikgKyBnZ3RpdGxlKCJUZXhhcyBTcHJlYWQgb2YgQ09WSUQtMTkiKSsKICAjIHNjYWxlX2ZpbGxfbWFudWFsKGxvdz0icmVkIiwgbWlkPSJncmV5IiwgaGlnaD0iYmx1ZSIpCiAgc2NhbGVfZmlsbF9ncmFkaWVudChsb3cgPSAiZ3JleSIsIGhpZ2ggPSAicmVkIiwgbmEudmFsdWUgPSBOQSkKZ2dzYXZlKCIuLy4uL2ltZ3MvdHhfc3ByZWFkX2RheXMucG5nIikKICAjIHNjYWxlX2ZpbGxfZ3JhZGllbnQobG93PSJyZWQiLCBtaWQ9ImdyZXkiLCBoaWdoPSJibHVlIikKICAjIHNjYWxlX2ZpbGxfZ3JhZGllbnRuKCkKICAjIHNjYWxlX2NvbG91cl9ncmFkaWVudDIoKQogIApgYGAKYGBge3J9CgpgYGAKCgoKCgo=